如何在Swift中正确地测试Core Data

9

已经有很多关于这个主题的内容了,但我还没有找到适用于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)

问题出在将在测试中创建的MOC传递给执行操作的类。由于实体类有命名空间,Core Data无法获取适当的ManagedObject子类并返回一个NSManagedObject集合。当循环或对这些对象进行任何操作时(在您的类中将是测试项数组[TestItem]),会出现问题。
例如,有问题的类ItemDateCoordinator将执行此循环(从NSFetchRequest中拉取相关数据后):
for testItem in testItems {
    testItem.doPart(numberOfDays: 10)
}

会导致以下错误:

致命错误:NSArray元素未能匹配Swift Array Element类型

此外,我遇到了一些信息收集,但没有一个确定的答案:

  • 在创建实体时转换实体,我一直在使用Jesse的解决方案,但在更大范围的测试中不起作用。
  • 在另一个问题上发布了一个解决方案,涉及在运行时交换类,但在实体继承方面对我没有起作用。
  • 在这种情况下,是否有其他测试对象Core Data的方法?你是如何做到的?

你是否遇到了一个嘲讽的问题? - Mustafa Ibrahim
2个回答

13

我本来想让你看一下Swift,Core Data和单元测试的,但看到你已经找到了。

那篇文章并没有详细说明您的文件应该存在哪里(即在哪个目标中)。您不应该将NSManagedObject子类(或任何文件)添加到两个目标中。我发现这会导致各种难以发现的错误和晦涩的错误。

绝对不要执行这种方法。那是一个可怕的hack。

相反,使您的类公开并在XCTestCase文件中导入MyAppTarget。更好的方法是,您的模型应该在自己的框架中,就像我最近在演讲中提到的那样(视频将在几周后发布在realm.io上)。这样做可以使您的模型命名空间非常清晰,并且通常更容易处理。然后,在访问托管对象时,您需要在所有地方导入MyAppModel

我还有一个新的框架,JSQCoreDataKit,旨在使Swift中使用Core Data变得更容易。这个框架的一个关键部分是CoreDataStack,您可以使用其中一个内存存储来初始化您的测试。有带示例的演示应用程序,以及注释良好的单元测试。


谢谢,这是最终让我找到解决方案的答案(Xcode 7,Swift 2)。只将您的NSManagedObject子类文件添加到主目标中,而不是测试目标中。我发现没有必要使它们公开(我认为这是Xcode 7的变化)。在我的测试文件顶部,我添加了:@testable import MY_MODULE_NAME。 - SarahR
通过使用@testable import ModuleName,可以像这里描述的那样解决问题;https://www.natashatherobot.com/swift-2-xcode-7-unit-testing-access/ - Henrik Hartz

4
我相信最近更新了这个功能(iOS 9/Swift 2.0),在导入目标时使用了可测试的关键字,意味着目标的内部类(默认)变为公共类。从文档中得知:

enter image description here

所以,补充一下jessesquires的答案,将@testable附加到您的导入中,这应该解决单元测试错误:

@testable import MyAppTarget

+1 我已经在一个Swift 3.0的示例项目中使用了你的解决方案(https://github.com/Daemon-Devarshi/MedicationSchedulerSwift3.0/tree/master/MedicationTests),它运行得非常顺畅 :-) - Devarshi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接