单元测试中的新核心数据堆栈(PersistenceController)

Posted

技术标签:

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

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

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

一般来说,测试使用 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),到目前为止它正在工作。

以上是关于单元测试中的新核心数据堆栈(PersistenceController)的主要内容,如果未能解决你的问题,请参考以下文章

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

JPA的核心配置

Google 应用引擎的 gradle 单元测试在哪里期望 persistence.xml?

JPA核心类与使用

用于单元测试的内存存储中的 iOS 10 核心数据

persistence.xml 中的多个持久性单元相互创建表