gpt4 book ai didi

unit-testing - 具有内存存储的核心数据堆栈的单元测试不断失败

转载 作者:行者123 更新时间:2023-12-03 21:27:03 36 4
gpt4 key购买 nike

我正在建立一个个人项目,让我和我的妻子监控我们的杂货消费习惯。该应用程序使用了 Core Data,我在进行单元测试时遇到了困难。我正在测试我的 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

    我做错了什么导致这些测试失败?

    最佳答案

    不幸的是,batch deletes are not supported with CoreData in-memory stores :

    Important: Batch deletes are only available when you are using a SQLite persistent store.

    关于unit-testing - 具有内存存储的核心数据堆栈的单元测试不断失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44887539/

    36 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com