OCMock:存根 @dynamic 属性

Posted

技术标签:

【中文标题】OCMock:存根 @dynamic 属性【英文标题】:OCMock: stub a @dynamic property 【发布时间】:2013-06-19 11:34:31 【问题描述】:

我正在尝试将单元测试添加到现有的 ios 应用程序中,其中使用 OCMock

在这个应用程序中,我们有一堆 CoreData 实体和生成的类。这些类显然包含@dynamic 属性。

我尝试按如下方式对这些属性之一进行存根:

self.event = [OCMockObject mockForClass:[ACEvent class]];
[[[self.event stub] andReturn:@"e46e1555-d866-4160-9b42-36d0fb9c29cd"] eventGUID];

关键是,它不起作用。显然是因为 @dynamic 属性默认没有实现,在这种情况下依赖 CoreData 来提供它。我最终得到一个 NSError:

-[NSProxy doesNotRecognizeSelector:eventGUID] called!

我已经看到其他问题通过将 CoreData 实体抽象为协议 (OCMock with Core Data dynamic properties problem) 来解决。但由于这是一个现有的代码库,我没有这个选项,因为我负担不起重构所有内容。

谁能提供另一种解决方案?

编辑: 作为旁注,我刚刚找到了一个解决方案,但我担心它不能在所有情况下都有效。 我所做的是在测试目标中为这些方法提供了一个示例的空实现。它可以工作,但我担心它会破坏其他依赖 CoreData 工作的测试。对此有何见解?

【问题讨论】:

在类别中使用空方法应该可以。 OCMock 需要实现的原因是必须弄清楚方法签名是什么。一旦它知道存根应该工作。如果 OCMock 在模拟类中找不到方法,也许我们可以添加一些东西,让 OCMock 假定一个没有参数的方法和一个 id 返回类型。不过,这似乎有点脆弱。 【参考方案1】:

使用 OCMock,我总是为每个托管对象创建一个协议,然后为这些协议创建模拟,但正如你所说,你不能这样做,所以我建议创建一个与你在代码中使用的相同属性的假类你想测试(对于每个NSManagedObject),然后在传递那些假对象时只使用强制转换(你可以使用 OCMock 并存根你想要的方法,或者只是创建一个假类的对象并设置你想要的属性) .

【讨论】:

【参考方案2】:

上面的答案让我不满意,因为我不喜欢为此创建协议。所以我发现有一种更简单的方法可以做到这一点。而不是

[[[self.event stub] andReturn:@"e46e1555-d866-4160-9b42-36d0fb9c29cd"] eventGUID];

随便写

[[[self.event stub] andReturn:@"e46e1555-d866-4160-9b42-36d0fb9c29cd"] valueForKey:@"eventGUID"];

【讨论】:

刚刚尝试使用最新版本的 OCMock。它没有用。看来核心数据不使用 valueForKey:。 :-(

以上是关于OCMock:存根 @dynamic 属性的主要内容,如果未能解决你的问题,请参考以下文章

OCMock 不能存根分类方法

通过 OCMock 存根覆盖方法

OCMock 中的存根类方法

是否可以使用 OCMock 存根 NSProcessInfo?

OCMock:存根从不匹配签名

OCMock: OCMPartialMock 对象调用实际方法而不是存根