[英]Unit test core data with multiple entities
I would like to test my core data methode.我想测试我的核心数据方法。 There is multiples entities in my coredataModel and for each I have a NSManagedObject class there is methode inside those classes to add, delete and remove data of the corresponding entity.
我的 coredataModel 中有多个实体,每个实体都有一个 NSManagedObject class 在这些类中有添加、删除和删除相应实体数据的方法。
public class StoredGame: NSManagedObject {
static private let storage = DataManager.shared.storage
static var all: [Game] {
let request: NSFetchRequest<StoredGame> = StoredGame.fetchRequest()
guard let storedGame = try? storage.viewContext.fetch(request) else { return [] }
var games: [Game] = .init()
storedGame.forEach { (storedGame) in
games.append(convert(storedGame))
}
return games
}
static func add(new game: Game) {
let entity = NSEntityDescription.entity(forEntityName: "StoredGame", in: storage.viewContext)!
let newGame = StoredGame(entity: entity, insertInto: storage.viewContext)
try? storage.saveContext()
}
}
and then I have a class responsible of the core data stack然后我有一个负责核心数据堆栈的 class
class CoreDataManager {
private lazy var persistentContainer: NSPersistentContainer! = {
guard let modelURL = Bundle.main.url(forResource: "CoreData", withExtension:"momd") else {
fatalError("Error loading model from bundle")
}
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
guard let mom = NSManagedObjectModel(contentsOf: modelURL) else {
fatalError("Error initializing mom from: \(modelURL)")
}
let container = NSPersistentContainer(name: "CoreData", managedObjectModel: mom)
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
var viewContext: NSManagedObjectContext {
return persistentContainer.viewContext
}
func saveContext () throws {
let context = viewContext
if context.hasChanges {
do {
try context.save()
} catch(let error) {
print(error)
}
}
}
}
Then when it goes to the tests.然后当它进行测试时。 I've created a mockContainer and a mockCoreData
我创建了一个 mockContainer 和一个 mockCoreData
lazy var mockContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "CoreData")
container.persistentStoreDescriptions[0].url = URL(fileURLWithPath: "/dev/null")
container.loadPersistentStores(completionHandler: { (_, error) in
XCTAssertNil(error)
})
return container
}()
lazy var mockCoreData = {
return StoredGame(context: mockContainer.viewContext)
}()
So now I dont know how to run tests in that configuration, I've tried a所以现在我不知道如何在该配置中运行测试,我尝试了
XCTAssert(StoredGame.all.isEmpty)
for exemple ( i have a all var in the StoredEntity class) XCTAssert(StoredGame.all.isEmpty)
例如(我在 StoredEntity 类中有一个 all var)
but it fails with an error telling但它失败并出现错误提示
'NSInvalidArgumentException', reason: '-[CoreData.StoredEntity setId:]: unrecognized selector sent to instance
any idea?任何想法?
This might be occurring with passing an invalid URL for the store description.为商店描述传递无效的 URL 可能会发生这种情况。 Unless you need to run tests with a NSSQLiteStoreType, which is the default for
NSPersistentContainer
, you may want to consider using an NSInMemoryStoreType for unit testing.除非您需要使用 NSSQLiteStoreType(这是
NSPersistentContainer
的默认值)运行测试,否则您可能需要考虑使用 NSInMemoryStoreType 进行单元测试。 A small tweak to your CoreDataManager
class could allow you to initialize the class both for your app and unit tests.对您的
CoreDataManager
进行一个小调整可以让您为您的应用程序和单元测试初始化 class。 For example:例如:
class CoreDataManager {
private let persisted: Bool
init(persisted: Bool = true) {
self.persisted = persisted
}
lazy var persistentContainer: NSPersistentContainer = {
let description = NSPersistentStoreDescription()
if persisted {
description.type = NSSQLiteStoreType
description.url = // location to store the db.
} else {
description.type = NSInMemoryStoreType
}
let container = NSPersistentContainer(name: "CoreData")
container.persistentStoreDescriptions = [description]
container.loadPersistentStores //...
return container
}()
}
Then you can use this exact class in your unit tests without need to create a mock.然后,您可以在单元测试中使用这个精确的 class 而无需创建模拟。 Just initialize it without persistence:
只需初始化它而无需持久性:
let manager = CoreDataManager(persisted: false)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.