我正在使用XCTest和OCMock 2.2.1进行单元测试。我有一个类使用以下方法获取包标识符:
NSString *bundleIdentifier = [[NSBundle bundleForClass:[self class]] bundleIdentifier];
在运行应用程序或特别是此类的单元测试时,这可以正常工作。
在对其他类进行测试时,我正在部分模拟此对象,但仍需要获取包标识符的方法。
我所看到的是在将对象实例传递给+ [OCMockObject partialMockForObject:]
之前看起来是正确的:
(lldb) po myObject
<MyObject: 0x1006ec480>
(lldb) po [NSBundle bundleForClass:[myObject class]]
NSBundle </Users/paynerc/Library/Developer/Xcode/DerivedData/xxxx/Build/Products/Debug/MyTests Tests.xctest> (loaded)
(lldb) po [[NSBundle bundleForClass:[myObject class]] bundleIdentifier]
com.paynerc.MyBundle
然而,在我将myObject
传递给[OCMockObject partialMockForObject:myObject]
之后,情况发生了变化:
(lldb) po myObject
<MyObject-0x1006ec480-401894396.880136: 0x1006ec480>
(lldb) po [NSBundle bundleForClass:[myObject class]]
NSBundle </Applications/Xcode.app/Contents/Developer/usr/bin> (loaded)
(lldb) po [[NSBundle bundleForClass:[myObject class]] bundleIdentifier]
nil
对象被修改并包含部分模拟魔法的事实是有道理的。似乎没有意义的是为什么对bundleForClass
的调用改变了它返回的内容。
我能做些什么来确保bundleForClass
继续返回原始值,而不是模仿MyObject中的调用?关注的是,在另一个单元测试中需要部分模拟MyObject的其他人需要记住提供bundleForClass
的存根实现。
我目前的解决方案是请求捆绑标识符并检查结果。如果它是nil,我调用[NSBundle allBundles]
并迭代它们,直到找到一个具有非零bundleIdentifier的那个。虽然目前...... 正常工作 ...它是A)不是非常强大B)可怕的暴力 - 以及C)修改应用程序代码以支持单元测试。
有没有其他人遇到过这个并提出更好的解决方案?
答案 0 :(得分:3)
运行时运行正常。模拟对象是NSProxy的子类,因此,对象的isa
与包之间的运行时绑定被有效地破坏(特别是isa
指向Class
然后通过dyld
API查找,以确定从中加载的mach-o图像, 用于查找包。)
OCMockObject
代理(或子类OCPartialMockObject
)上可能存在允许您检索原始类的API。您必须使用那些,当然,这意味着您将使用仅应在测试中使用的模拟调用来污染您的代码。
或者,在bundle / framework中的一个类上实现一个类方法,或者返回类的包。那不应该被嘲笑。