【问题标题】:New Core Data Stack (PersistenceController) in Unit Tests单元测试中的新核心数据堆栈(PersistenceController)
【发布时间】:2020-09-16 01:42:57
【问题描述】:

使用新的 Swift App Xcode 模板,我看到 PersistenceController 结构添加了 sharedpreview 实例以用作核心数据堆栈。据我了解,preview 实例用于 SwiftUI 预览。

如果我有一个接受我的核心数据堆栈实例的服务类,我应该使用preview 实例作为我的单元测试的一部分吗?或者我应该创建某种间谍/伪造来传递到我正在测试的服务类中?

一般来说,测试使用 Core Data 的类的最佳实践是什么?

【问题讨论】:

    标签: unit-testing core-data


    【解决方案1】:

    我也在研究这个。我没有找到最佳实践。所以我会总结一下我的工作。 PersistenceController 是一个不错的模式。

    静态变量预览允许您创建不同的商店并向其中添加一些对象,例如

      static var preview: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        // this is the part where you can add mock data
        for _ in 0..<10 {
            let newItem = Note(context: viewContext)
            newItem.creationDate = Date()
        }
        do {
            try viewContext.save()
        } catch {
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        }
        return result
    }()
    

    对于单元测试,我们希望从一个空存储开始,所以我只是在 PersistenceController 中添加了一个 var

    static let unitTest: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        //empty store
        return result
    }()
    

    这使我的单元测试看起来像

    class TestCoreDataStack: XCTestCase {
    
    var coreDataStack: PersistenceController!
    
    override func setUp() {
        super.setUp()
        coreDataStack = PersistenceController.unitTest
    }
    
    override func tearDown() {
      super.tearDown()
       //called after the invocation of each test method in the class.
       // I am deleted all notes to start fresh for the next test
      UnitTestHelpers.deleteAllNotes(container: coreDataStack.container)  
      coreDataStack = nil
    }
    
    func testAddNote() {
        let context = coreDataStack.container.viewContext
        
        let title = "my new title"
        let note = Note(title: title, context: context)
        
        XCTAssertNotNil(note, "note should not be nil")
        XCTAssertTrue(note.title == title)
        XCTAssertNotNil(note.creationDate, "notes date should not be nil")
    
    } }
    

    【讨论】:

    • 我喜欢这个解决方案,但发现单元测试持久性控制器在测试之间没有重新初始化存在问题,而且我不想每次都手动删除所有内容。最后,我只是在设置中调用coreDataStack = PersistenceController(inMemory: true),到目前为止它正在工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    • 2015-10-24
    • 1970-01-01
    • 2015-04-15
    相关资源
    最近更新 更多