2017-07-03 68 views
2

我正在構建一個個人項目,以允許我的妻子和我監視我們的雜貨消費習慣。該應用程序使用核心數據,我的單元測試遇到困難。我正在測試我的CoreDataStack類,以確保其方法保存並刪除對象。核心數據堆棧與內存存儲單元測試失敗

這裏是CoreDataStack

internal class CoreDataStack { 

    // MARK: - Properties 

    private let modelName: String 

    internal lazy var storeContainer: NSPersistentContainer = { 
     let container = NSPersistentContainer(name: self.modelName) 
     container.loadPersistentStores { (storeDescription, error) in 
      if let error = error as NSError? { 
       fatalError("Unresolved error \(error), \(error.userInfo)") 
      } 
     } 
     return container 
    }() 

    internal lazy var managedContext: NSManagedObjectContext = { 
     return self.storeContainer.viewContext 
    }() 

    // MARK: - Initialization 

    internal init(modelName: String = "Cart") { 
     self.modelName = modelName 
    } 

    // MARK: - Saving 

    internal func saveContext() { 
     guard managedContext.hasChanges else { 
      return 
     } 
     do { 
      try managedContext.save() 
     } catch let error as NSError { 
      fatalError("Unresolved error \(error), \(error.userInfo)") 
     } 
    } 

    // MARK: - Deleting 

    internal func delete(object: NSManagedObject, from context: NSManagedObjectContext) { 
     context.delete(object) 
    } 

    internal func delete(allObjectsForEntity entity: String, from context: NSManagedObjectContext) { 
     let deleteFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity) 
     let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetchRequest) 
     do { 
      try storeContainer.persistentStoreCoordinator.execute(batchDeleteRequest, with: context) 
     } catch let error as NSError { 
      fatalError("Unresolved error \(error), \(error.userInfo)") 
     } 
    } 

} 

我創建的CoreDataStack一個子類,叫做TestCoreDataStack,在我的測試目標。 TestCoreDataStack使用內存中的存儲,以便在包含測試完成時將其銷燬。

這裏是TestCoreDataStack

internal final class TestCoreDataStack: CoreDataStack { 

    // MARK: - Initialization 

    internal override init(modelName: String = "Cart") { 
     super.init(modelName: modelName) 
     let persistentStoreDescription = NSPersistentStoreDescription() 
     persistentStoreDescription.type = NSInMemoryStoreType 
     let container = NSPersistentContainer(name: modelName) 
     container.persistentStoreDescriptions = [persistentStoreDescription] 
     container.loadPersistentStores { (storeDescription, error) in 
      if let error = error as NSError? { 
       fatalError("Unresolved error \(error), \(error.userInfo)") 
      } 
     } 
     self.storeContainer = container 
    } 
} 

我也有一個輔助類,ManagedObjectFetcher,這是隻有在我的測試目標包括,只是爲了獲取管理對象將它們保存或刪除後。這個類用於使我可以驗證計數,並且在保存或刪除對象後存在正確的信息。

她的是ManagedObjectFetcher

internal final class ManagedObjectFetcher { 

    // MARK: - Properties 

    private let coreDataStack: CoreDataStack 

    // MARK: - Initialization 

    internal init(coreDataStack: CoreDataStack) { 
     self.coreDataStack = coreDataStack 
    } 

    // MARK: - All Records 

    internal func allRecords<T: NSManagedObject>(for entity : T.Type) -> [T] { 
     let request = T.fetchRequest() 
     do { 
      guard let results = try coreDataStack.managedContext.fetch(request) as? [T] else { 
       fatalError("Invalid results") 
      } 
      return results 
     } catch { 
      fatalError("Error with request: \(error)") 
     } 
    } 

} 

CoreDataStackTests是我XCTestCase子類測試CoreDataStack確保對象將被保存或刪除。

這裏是CoreDataStackTests

internal final class CoreDataStackTests: XCTestCase { 

    // MARK: - Properties 

    private var coreDataStack: TestCoreDataStack! 

    private var managedObjectFetcher: ManagedObjectFetcher! 

    // MARK: - Test Lifecycle 

    override func setUp() { 
     super.setUp() 
     coreDataStack = TestCoreDataStack() 
     managedObjectFetcher = ManagedObjectFetcher(coreDataStack: coreDataStack) 
    } 

    override func tearDown() { 
     coreDataStack = nil 
     managedObjectFetcher = nil 
     super.tearDown() 
    } 

    // MARK: - Saving 

    // Test 1 
    internal func test_CoreDataStack_Saves_GroceryItem() { 
     let preResults = managedObjectFetcher.allRecords(for: GroceryItem.self) 
     XCTAssertEqual(preResults.count, 0, "Expected `0`") 
     let _ = GroceryItem(name: "Name", singleItemPrice: Decimal(0.99), quantity: 1, date: Date(), isTaxable: true, managedObjectContext: coreDataStack.managedContext) 
     coreDataStack.saveContext() 
     let postResults = managedObjectFetcher.allRecords(for: GroceryItem.self) 
     XCTAssertEqual(postResults.count, 1, "Expected `1`") 
    } 

    // MARK: - Deleting 

    // Test 2 
    internal func test_CoreDataStack_Deletes_GroceryItem() { 
     let initialResults = managedObjectFetcher.allRecords(for: GroceryItem.self) 
     XCTAssertEqual(initialResults.count, 0, "Expected `0`") 
     let item = GroceryItem(name: "Name", singleItemPrice: Decimal(0.99), quantity: 1, date: Date(), isTaxable: true, managedObjectContext: coreDataStack.managedContext) 
     coreDataStack.saveContext() 
     let preResults = managedObjectFetcher.allRecords(for: GroceryItem.self) 
     XCTAssertEqual(preResults.count, 1, "Expected `1`") 
     coreDataStack.delete(object: item, from: coreDataStack.managedContext) 
     coreDataStack.saveContext() 
     let postResults = managedObjectFetcher.allRecords(for: GroceryItem.self) 
     XCTAssertEqual(postResults.count, 0, "Expected `0`") 
    } 

    // Test 3 
    internal func test_CoreDataStack_Deletes_AllGroceryItems() { 
     let initialResults = managedObjectFetcher.allRecords(for: GroceryItem.self) 
     XCTAssertEqual(initialResults.count, 0, "Expected `0`") 
     let _ = GroceryItem(name: "Name", singleItemPrice: Decimal(0.99), quantity: 1, date: Date(), isTaxable: true, managedObjectContext: coreDataStack.managedContext) 
     let _ = GroceryItem(name: "Another Name", singleItemPrice: Decimal(5.99), quantity: 2, date: Date(), isTaxable: false, managedObjectContext: coreDataStack.managedContext) 
     coreDataStack.saveContext() 
     let preResults = managedObjectFetcher.allRecords(for: GroceryItem.self) 
     XCTAssertEqual(preResults.count, 2, "Expected `2`") 
     coreDataStack.delete(allObjectsForEntity: GroceryItem.description(), from: coreDataStack.managedContext) 
     coreDataStack.saveContext() 
     let postResults = managedObjectFetcher.allRecords(for: GroceryItem.self) 
     XCTAssertEqual(postResults.count, 0, "Expected `0`") 
    } 

} 

CoreDataStackTests執行的測試中,我遇到了以下問題,我解決不了:

  • 測試1:測試通過當單獨跑。當所有測試CoreDataStack測試運行時,它通過或失敗。
  • 測試2:測試通過獨立運行。當所有測試CoreDataStack測試運行時,它通過或失敗。
  • 測試3:無論是單獨測試還是與其他測試一起運行,測試都不會通過。在每次運行時,測試失敗斷點在try storeContainer.persistentStoreCoordinator.execute(batchDeleteRequest, with: context)delete(allObjectsForEntity entity: String, from context: NSManagedObjectContext)方法CoreDataStack內被擊中。

這是控制檯輸出,我正在運行的所有三個測試後得到:

Test Suite 'Selected tests' started at 2017-07-03 21:24:01.609 
Test Suite 'CartTests.xctest' started at 2017-07-03 21:24:01.610 
Test Suite 'CoreDataStackTests' started at 2017-07-03 21:24:01.610 
Test Case '-[CartTests.CoreDataStackTests test_CoreDataStack_Deletes_AllGroceryItems]' started. 
<unknown>:0: error: -[CartTests.CoreDataStackTests test_CoreDataStack_Deletes_AllGroceryItems] : failed: caught "NSInternalInconsistencyException", "Unknown command type <NSBatchDeleteRequest : resultType : 0, fetch :<NSFetchRequest: 0x6000000de450> (entity: GroceryItem; predicate: ((null)); sortDescriptors: ((null)); type: NSManagedObjectIDResultType; includesPropertyValues: NO; includesPendingChanges: NO;) >" 
(
    0 CoreFoundation      0x000000010c90079b __exceptionPreprocess + 171 
    1 libobjc.A.dylib      0x000000010bd2e121 objc_exception_throw + 48 
    2 CoreData       0x000000010c34febf -[NSMappedObjectStore executeRequest:withContext:error:] + 303 
    3 CoreData       0x000000010c3f0f6d __65-[NSPersistentStoreCoordinator executeRequest:withContext:error:]_block_invoke + 2509 
    4 CoreData       0x000000010c3e9126 __55-[NSPersistentStoreCoordinator _routeHeavyweightBlock:]_block_invoke + 86 
    5 CoreData       0x000000010c3fcda9 gutsOfBlockToNSPersistentStoreCoordinatorPerform + 185 
    6 libdispatch.dylib     0x0000000110bfbbb9 _dispatch_client_callout + 8 
    7 libdispatch.dylib     0x0000000110c02500 _dispatch_queue_barrier_sync_invoke_and_complete + 92 
    8 CoreData       0x000000010c3e8ab5 _perform + 213 
    9 CoreData       0x000000010c3e8e3b -[NSPersistentStoreCoordinator _routeHeavyweightBlock:] + 283 
    10 CoreData       0x000000010c2f2aba -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 634 
    11 Cart        0x000000010b40b667 _T04Cart13CoreDataStackC16deleteAllObjectsySS9forEntity_So22NSManagedObjectContextC4fromtF + 391 
    12 CartTests       0x00000001240ea070 _T09CartTests013CoreDataStackB0C05test_cdE24_Deletes_AllGroceryItemsyyF + 3344 
    13 CartTests       0x00000001240eabc4 _T09CartTests013CoreDataStackB0C05test_cdE24_Deletes_AllGroceryItemsyyFTo + 36 
    14 CoreFoundation      0x000000010c884f8c __invoking___ + 140 
    15 CoreFoundation      0x000000010c884e60 -[NSInvocation invoke] + 320 
    16 XCTest        0x00000001224dd6e0 __24-[XCTestCase invokeTest]_block_invoke_2 + 451 
    17 XCTest        0x0000000122524bed -[XCUITestContext performInScope:] + 187 
    18 XCTest        0x00000001224dd4f8 -[XCTestCase invokeTest] + 254 
    19 XCTest        0x00000001224de424 __26-[XCTestCase performTest:]_block_invoke.362 + 42 
    20 XCTest        0x0000000122529432 +[XCTContext runInContextForTestCase:block:] + 163 
    21 XCTest        0x00000001224dddc0 -[XCTestCase performTest:] + 608 
    22 XCTest        0x00000001224da396 __27-[XCTestSuite performTest:]_block_invoke + 295 
    23 XCTest        0x00000001224d9f8d -[XCTestSuite _performProtectedSectionForTest:testSection:] + 26 
    24 XCTest        0x00000001224da171 -[XCTestSuite performTest:] + 214 
    25 XCTest        0x00000001224da396 __27-[XCTestSuite performTest:]_block_invoke + 295 
    26 XCTest        0x00000001224d9f8d -[XCTestSuite _performProtectedSectionForTest:testSection:] + 26 
    27 XCTest        0x00000001224da171 -[XCTestSuite performTest:] + 214 
    28 XCTest        0x00000001224da396 __27-[XCTestSuite performTest:]_block_invoke + 295 
    29 XCTest        0x00000001224d9f8d -[XCTestSuite _performProtectedSectionForTest:testSection:] + 26 
    30 XCTest        0x00000001224da171 -[XCTestSuite performTest:] + 214 
    31 XCTest        0x0000000122530625 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke + 40 
    32 XCTest        0x00000001224ecb99 -[XCTestObservationCenter _observeTestExecutionForBlock:] + 480 
    33 XCTest        0x00000001225304c4 -[XCTTestRunSession runTestsAndReturnError:] + 281 
    34 XCTest        0x00000001224c9d43 -[XCTestDriver runTestsAndReturnError:] + 254 
    35 XCTest        0x00000001225286b7 _XCTestMain + 616 
    36 CoreFoundation      0x000000010c8a3dcc __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12 
    37 CoreFoundation      0x000000010c88833b __CFRunLoopDoBlocks + 203 
    38 CoreFoundation      0x000000010c887b34 __CFRunLoopRun + 1060 
    39 CoreFoundation      0x000000010c887499 CFRunLoopRunSpecific + 409 
    40 GraphicsServices     0x00000001121d79d7 GSEventRunModal + 62 
    41 UIKit        0x000000010cd7f0b8 UIApplicationMain + 159 
    42 Cart        0x000000010b40e637 main + 55 
    43 libdyld.dylib      0x0000000110c71771 start + 1 
    44 ???         0x0000000000000005 0x0 + 5 
) 
Test Case '-[CartTests.CoreDataStackTests test_CoreDataStack_Deletes_AllGroceryItems]' failed (2636.006 seconds). 
Test Case '-[CartTests.CoreDataStackTests test_CoreDataStack_Deletes_GroceryItem]' started. 
<unknown>:0: error: -[CartTests.CoreDataStackTests test_CoreDataStack_Deletes_GroceryItem] : failed: caught "NSInvalidArgumentException", "executeFetchRequest:error: <null> is not a valid NSFetchRequest." 
(
    0 CoreFoundation      0x000000010c90079b __exceptionPreprocess + 171 
    1 libobjc.A.dylib      0x000000010bd2e121 objc_exception_throw + 48 
    2 CoreData       0x000000010c2f11d8 -[NSManagedObjectContext executeFetchRequest:error:] + 792 
    3 CartTests       0x00000001240eb1f7 _T09CartTests20ManagedObjectFetcherC10allRecordsSayxGxm3for_tSo09NSManagedD0CRbzlF + 247 
    4 CartTests       0x00000001240e7d86 _T09CartTests013CoreDataStackB0C05test_cdE20_Deletes_GroceryItemyyF + 182 
    5 CartTests       0x00000001240e9344 _T09CartTests013CoreDataStackB0C05test_cdE20_Deletes_GroceryItemyyFTo + 36 
    6 CoreFoundation      0x000000010c884f8c __invoking___ + 140 
    7 CoreFoundation      0x000000010c884e60 -[NSInvocation invoke] + 320 
    8 XCTest        0x00000001224dd6e0 __24-[XCTestCase invokeTest]_block_invoke_2 + 451 
    9 XCTest        0x0000000122524bed -[XCUITestContext performInScope:] + 187 
    10 XCTest        0x00000001224dd4f8 -[XCTestCase invokeTest] + 254 
    11 XCTest        0x00000001224de424 __26-[XCTestCase performTest:]_block_invoke.362 + 42 
    12 XCTest        0x0000000122529432 +[XCTContext runInContextForTestCase:block:] + 163 
    13 XCTest        0x00000001224dddc0 -[XCTestCase performTest:] + 608 
    14 XCTest        0x00000001224da396 __27-[XCTestSuite performTest:]_block_invoke + 295 
    15 XCTest        0x00000001224d9f8d -[XCTestSuite _performProtectedSectionForTest:testSection:] + 26 
    16 XCTest        0x00000001224da171 -[XCTestSuite performTest:] + 214 
    17 XCTest        0x00000001224da396 __27-[XCTestSuite performTest:]_block_invoke + 295 
    18 XCTest        0x00000001224d9f8d -[XCTestSuite _performProtectedSectionForTest:testSection:] + 26 
    19 XCTest        0x00000001224da171 -[XCTestSuite performTest:] + 214 
    20 XCTest        0x00000001224da396 __27-[XCTestSuite performTest:]_block_invoke + 295 
    21 XCTest        0x00000001224d9f8d -[XCTestSuite _performProtectedSectionForTest:testSection:] + 26 
    22 XCTest        0x00000001224da171 -[XCTestSuite performTest:] + 214 
    23 XCTest        0x0000000122530625 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke + 40 
    24 XCTest        0x00000001224ecb99 -[XCTestObservationCenter _observeTestExecutionForBlock:] + 480 
    25 XCTest        0x00000001225304c4 -[XCTTestRunSession runTestsAndReturnError:] + 281 
    26 XCTest        0x00000001224c9d43 -[XCTestDriver runTestsAndReturnError:] + 254 
    27 XCTest        0x00000001225286b7 _XCTestMain + 616 
    28 CoreFoundation      0x000000010c8a3dcc __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12 
    29 CoreFoundation      0x000000010c88833b __CFRunLoopDoBlocks + 203 
    30 CoreFoundation      0x000000010c887b34 __CFRunLoopRun + 1060 
    31 CoreFoundation      0x000000010c887499 CFRunLoopRunSpecific + 409 
    32 GraphicsServices     0x00000001121d79d7 GSEventRunModal + 62 
    33 UIKit        0x000000010cd7f0b8 UIApplicationMain + 159 
    34 Cart        0x000000010b40e637 main + 55 
    35 libdyld.dylib      0x0000000110c71771 start + 1 
    36 ???         0x0000000000000005 0x0 + 5 
) 
Test Case '-[CartTests.CoreDataStackTests test_CoreDataStack_Deletes_GroceryItem]' failed (11.969 seconds). 
Test Case '-[CartTests.CoreDataStackTests test_CoreDataStack_Saves_GroceryItem]' started. 
<unknown>:0: error: -[CartTests.CoreDataStackTests test_CoreDataStack_Saves_GroceryItem] : failed: caught "NSInvalidArgumentException", "executeFetchRequest:error: <null> is not a valid NSFetchRequest." 
(
    0 CoreFoundation      0x000000010c90079b __exceptionPreprocess + 171 
    1 libobjc.A.dylib      0x000000010bd2e121 objc_exception_throw + 48 
    2 CoreData       0x000000010c2f11d8 -[NSManagedObjectContext executeFetchRequest:error:] + 792 
    3 CartTests       0x00000001240eb1f7 _T09CartTests20ManagedObjectFetcherC10allRecordsSayxGxm3for_tSo09NSManagedD0CRbzlF + 247 
    4 CartTests       0x00000001240e6fe6 _T09CartTests013CoreDataStackB0C05test_cdE18_Saves_GroceryItemyyF + 182 
    5 CartTests       0x00000001240e7cb4 _T09CartTests013CoreDataStackB0C05test_cdE18_Saves_GroceryItemyyFTo + 36 
    6 CoreFoundation      0x000000010c884f8c __invoking___ + 140 
    7 CoreFoundation      0x000000010c884e60 -[NSInvocation invoke] + 320 
    8 XCTest        0x00000001224dd6e0 __24-[XCTestCase invokeTest]_block_invoke_2 + 451 
    9 XCTest        0x0000000122524bed -[XCUITestContext performInScope:] + 187 
    10 XCTest        0x00000001224dd4f8 -[XCTestCase invokeTest] + 254 
    11 XCTest        0x00000001224de424 __26-[XCTestCase performTest:]_block_invoke.362 + 42 
    12 XCTest        0x0000000122529432 +[XCTContext runInContextForTestCase:block:] + 163 
    13 XCTest        0x00000001224dddc0 -[XCTestCase performTest:] + 608 
    14 XCTest        0x00000001224da396 __27-[XCTestSuite performTest:]_block_invoke + 295 
    15 XCTest        0x00000001224d9f8d -[XCTestSuite _performProtectedSectionForTest:testSection:] + 26 
    16 XCTest        0x00000001224da171 -[XCTestSuite performTest:] + 214 
    17 XCTest        0x00000001224da396 __27-[XCTestSuite performTest:]_block_invoke + 295 
    18 XCTest        0x00000001224d9f8d -[XCTestSuite _performProtectedSectionForTest:testSection:] + 26 
    19 XCTest        0x00000001224da171 -[XCTestSuite performTest:] + 214 
    20 XCTest        0x00000001224da396 __27-[XCTestSuite performTest:]_block_invoke + 295 
    21 XCTest        0x00000001224d9f8d -[XCTestSuite _performProtectedSectionForTest:testSection:] + 26 
    22 XCTest        0x00000001224da171 -[XCTestSuite performTest:] + 214 
    23 XCTest        0x0000000122530625 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke + 40 
    24 XCTest        0x00000001224ecb99 -[XCTestObservationCenter _observeTestExecutionForBlock:] + 480 
    25 XCTest        0x00000001225304c4 -[XCTTestRunSession runTestsAndReturnError:] + 281 
    26 XCTest        0x00000001224c9d43 -[XCTestDriver runTestsAndReturnError:] + 254 
    27 XCTest        0x00000001225286b7 _XCTestMain + 616 
    28 CoreFoundation      0x000000010c8a3dcc __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12 
    29 CoreFoundation      0x000000010c88833b __CFRunLoopDoBlocks + 203 
    30 CoreFoundation      0x000000010c887b34 __CFRunLoopRun + 1060 
    31 CoreFoundation      0x000000010c887499 CFRunLoopRunSpecific + 409 
    32 GraphicsServices     0x00000001121d79d7 GSEventRunModal + 62 
    33 UIKit        0x000000010cd7f0b8 UIApplicationMain + 159 
    34 Cart        0x000000010b40e637 main + 55 
    35 libdyld.dylib      0x0000000110c71771 start + 1 
    36 ???         0x0000000000000005 0x0 + 5 
) 
Test Case '-[CartTests.CoreDataStackTests test_CoreDataStack_Saves_GroceryItem]' failed (4.826 seconds). 
Test Suite 'CoreDataStackTests' failed at 2017-07-03 22:08:14.412. 
Executed 3 tests, with 3 failures (3 unexpected) in 2652.801 (2652.802) seconds 
Test Suite 'CartTests.xctest' failed at 2017-07-03 22:08:14.413. 
Executed 3 tests, with 3 failures (3 unexpected) in 2652.801 (2652.803) seconds 
Test Suite 'Selected tests' failed at 2017-07-03 22:08:14.413. 
Executed 3 tests, with 3 failures (3 unexpected) in 2652.801 (2652.804) seconds 


Test session log: 

/var/folders/n9/48n8p_ms6rs2yc8vdkhq89br0000gn/T/com.apple.dt.XCTest/IDETestRunSession-44B21AFF-A887-42A9-8EF0-23B48DBC4744/CartTests-4BFEF3B5-D9B6-47D9-BA80-6007A7991D19/Session-CartTests-2017-07-03_212349-pZbWPl.log 

我在做什麼錯誤是導致這些測試失敗?

回答