如何在Swift中正确测试Core Data

时间:2015-04-14 00:25:29

标签: ios swift core-data nsmanagedobjectcontext

已经有相当多的主题,但我还没有找到一个适用于Swift(Xcode 6.2)的解决方案。

为了在Swift中测试Core Data支持的类,我生成了新的托管对象上下文,然后我将其注入到我的类中。

//Given   
let testManagedObjectContext = CoreDataTestComposer.setUpInMemoryManagedObjectContext()
let testItems = createFixtureData(testManagedObjectContext) as [TestItem]
self.itemDateCoordinator.managedObjectContext = testManagedObjectContext

//When
let data = self.itemDateCoordinator.do()

//Then
XCTAssert(data.exists)

问题来自于将在Test中创建的MOC传递给正在进行的类。由于实体类是命名空间的,因此Core Data不会获取相应的ManagedObject子类,而是返回NSManagedObject集。循环或对这些对象执行任何操作时(在您的类中,它将是一组测试项([TestItem])。

例如,违规类ItemDateCoordinator将执行此循环(在从NSFetchRequest拉出相关数据后)

for testItem in testItems {
    testItem.doPart(numberOfDays: 10)
}

会导致:

  

致命错误:NSArray元素无法匹配Swift数组元素类型

此外,我收到的信息集合没有太多可靠的答案:

  • 要在创建实体时强制转换实体,我一直在使用Jesse的解决方案,但这不适用于更大范围的测试。
  • 一个solution has been posted on another question涉及在运行时交换类,但这对我的实体继承没有用。
  • 在这种情况下,是否有其他方法可以使用Core Data测试对象?你怎么做呢?

2 个答案:

答案 0 :(得分:11)

我准备将您指向 Swift,核心数据和单元测试,但看到您已经找到它。 :)

该帖子并未详细说明您的文件应存在的位置(即,在哪个目标中)。您不应将<{1}}子类(或任何文件确实)添加到两个目标。我发现这会导致各种难以发现的错误和神秘的错误。

肯定不会this。这是一个可怕的黑客攻击。

相反,请在您的NSManagedObject文件中公开您的课程并import MyAppTarget。更好的是,正如我在最近的talk中提到的那样,你的模型应该在自己的框架中(视频将在几周内发布在realm.io上)。这样做可以使您的模型命名空间非常清晰,并且通常更容易处理。然后,您需要XCTestCase随处访问您的托管对象。

我还有一个新框架,JSQCoreDataKit旨在使Core Data更易于在Swift中使用。该框架的一个关键部分是import MyAppModel,您可以使用内存存储库为您的测试进行初始化。这里有一个带有示例的演示应用程序,以及评论良好的单元测试。

答案 1 :(得分:2)

我认为最近更新了(iOS 9 / Swift 2.0)以在导入的目标上使用testable关键字,这意味着目标的内部类(默认)变为公共类。来自文档:

enter image description here

所以要添加上面的jessesquires答案,将@testable添加到你的导入中,这应解决单元测试错误:

@testable import MyAppTarget