如何使用预先填充的SQLite文件使用具有内存存储类型的核心数据模型?

时间:2017-04-11 02:41:55

标签: unit-testing core-data

我正在关注来自Ray Wenderlich团队的过时tutorial,该团队使用命令行工具应用程序完成了Core Data支持的应用程序的重新填充。

我已成功预先填充了目标实体,并通过执行NSFetchRequest进行了验证。

现在,我想在单元测试中使用相同的预填充数据来验证我与CoreData的互动是否正确发生。我尝试将我的模拟CoreDataStack子类设置为使用内存存储,但是当我尝试验证我有预先填充的数据以便在我的单元测试中使用时,我得到的count { {1}}。

负责与我的应用程序目标0中的CoreData进行交互的类如下:

CoreDataStack

用于测试的/// The object that is responsible for managing interactions with Core Data. internal class CoreDataStack { // MARK: - Properties /// The name of the `NSManagedObjectModel` object used for storing information with Core Data. private let modelName: String /// The `NSManagedObjectContext` object that is associated with the main queue. internal lazy var mainContext: NSManagedObjectContext = { return self.storeContainer.viewContext }() /// The `NSPersistentContainer` object that encapsulates the application's Core Data stack. internal lazy var storeContainer: NSPersistentContainer = { let container = NSPersistentContainer(name: self.modelName) let directory = NSPersistentContainer.defaultDirectoryURL() let storeURL = directory.appendingPathComponent("\(self.modelName).sqlite") if !FileManager.default.fileExists(atPath: (storeURL.path)) { guard let populatedURL = Bundle.main.url(forResource: self.modelName, withExtension: "sqlite") else { fatalError("Invalid populated .sqlite file URL") } do { try FileManager.default.copyItem(at: populatedURL, to: storeURL) } catch { fatalError("Error: \(error)") } } let description = NSPersistentStoreDescription() description.url = storeURL container.persistentStoreDescriptions = [description] container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { fatalError("Error: \(error)") } }) return container }() // MARK: - Initialization /// Returns an instance of `CoreDataStack`. /// - parameter modelName: The name of the `NSManagedObjectModel` object used for storing information with Core Data. internal init(modelName: String) { self.modelName = modelName } /// Attempts to save items to Core Data by committing changes to `NSManagedObject`s in a `NSManagedObjectContext`. /// - parameter context: The `NSManagedObjectContext` of which changes should be committed. internal func saveContext(_ context: NSManagedObjectContext) { context.perform { do { try context.save() } catch let error as NSError { fatalError("Unresolved error \(error), \(error.userInfo)") } } } } CoreDataStack的子类如下:

MockCoreDataStack

在我的单元测试目标中,我的获取请求的internal class MockCoreDataStack: CoreDataStack { // MARK: - Initialization convenience init() { self.init(modelName: "Currency") } override init(modelName: String) { super.init(modelName: modelName) let container = NSPersistentContainer(name: modelName) let directory = NSPersistentContainer.defaultDirectoryURL() let storeURL = directory.appendingPathComponent("\(modelName).sqlite") if !FileManager.default.fileExists(atPath: (storeURL.path)) { guard let populatedURL = Bundle(for: type(of: self)).url(forResource: modelName, withExtension: "sqlite") else { fatalError("Invalid populated .sqlite file URL") } do { try FileManager.default.copyItem(at: populatedURL, to: storeURL) } catch { fatalError("Error: \(error)") } } let description = NSPersistentStoreDescription() description.url = storeURL description.type = NSInMemoryStoreType container.persistentStoreDescriptions = [description] container.loadPersistentStores { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } } self.storeContainer = container } } count0。我希望返回一个count,其中包含预填充对象的数量,就像我在应用程序目标中返回count时所得到的那样。

我做错了什么导致我没有返回预期的结果?

1 个答案:

答案 0 :(得分:0)

内存商店不使用商店网址。它只是在内存中创建一个空存储。

作为内存存储的替代方法,您可以在持久存储和实际使用的上下文之间创建父NSManagedObjectContext。 (但我不确定NSPersistentContainer会如何发挥作用。)

然后,当您想要重置回初始状态时,您只需rollback()父上下文。