当我尝试将核心数据与NSInMemoryStoreType
用于单元测试时,我总是会收到此错误:
Failed to find a unique match for an NSEntityDescription to a managed object subclass
这是我创建核心数据堆栈的目标:
public enum StoreType {
case sqLite
case binary
case inMemory
.................
}
public final class CoreDataStack {
var storeType: StoreType!
public init(storeType: StoreType) {
self.storeType = storeType
}
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Transaction")
container.loadPersistentStores(completionHandler: { (description, error) in
if let error = error {
fatalError("Unresolved error \(error), \(error.localizedDescription)")
} else {
description.type = self.storeType.type
}
})
return container
}()
public var context: NSManagedObjectContext {
return persistentContainer.viewContext
}
public func reset() {
for store in persistentContainer.persistentStoreCoordinator.persistentStores {
guard let url = store.url else { return }
try! persistentContainer.persistentStoreCoordinator.remove(store)
try! FileManager.default.removeItem(at: url)
}
}
}
这就是我在单元测试项目中使用它的方式:
class MyTests: XCTestCase {
var context: NSManagedObjectContext!
var stack: CoreDataStack!
override func setUp() {
stack = CoreDataStack(storeType: .inMemory)
context = stack.context
}
override func tearDown() {
stack.reset()
context = nil
}
}
从我读到的here看起来与我所遇到的问题相同,我必须在每次测试后清理所有测试,我认为我正在做。
我没有正确清理吗?还有另一种方法吗?
CoreDataStack
类是否已在您的应用程序中初始化?例如,在AppDelegate
课程?运行单元测试时,它将在测试运行之前的某个时间初始化AppDelegate
。我相信这是因为你的测试可以从应用程序调用任何东西来测试它,按照@testable import MyApp
这一行。如果您通过AppDelegate
和MyTests
初始化Core Data堆栈,那么您将加载Core Data堆栈两次。
需要注意的是,拥有两个或更多个NSPersistentContainer
实例意味着将两个或更多个NSManagedObjectModel
实例加载到内存中,这就是导致问题的原因。两个模型都在运行时提供额外的NSManagedObject
子类。当您尝试使用其中一个子类时,运行时不知道使用哪个(即使它们相同,它只是看到它们具有相同的名称)。我认为如果NSManagedObjectModel
可以处理这种情况会更好,但是目前由开发人员来确保加载的实例永远不会超过一个。