Objective c 呼叫+;部分模拟对象上的[NSBundle bundleForClass:]返回的结果与未模拟对象不同?

Objective c 呼叫+;部分模拟对象上的[NSBundle bundleForClass:]返回的结果与未模拟对象不同?,objective-c,ocmock,Objective C,Ocmock,我正在使用XTest和OCMock 2.2.1进行单元测试。我有一个类,该类使用以下方法获取捆绑包标识符: NSString *bundleIdentifier = [[NSBundle bundleForClass:[self class]] bundleIdentifier]; 尤其是在运行该类的应用程序或单元测试时,这会按照预期工作 在对其他类进行测试时,我部分模拟了这个对象,但仍然需要运行获取包标识符的方法 我看到的是在将对象实例传递给+[OCMockObject partialMoc

我正在使用XTest和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
对象被修改并包含部分模拟魔法这一事实是有道理的。似乎没有意义的是,为什么对
bundleForClass
的调用改变了它返回的内容

除了模拟MyObject内部的调用外,我是否可以做些什么来确保
bundleForClass
继续返回原始值?这里的问题是,任何其他需要在另一个单元测试中部分模拟MyObject的人都需要记住提供
bundleForClass
的存根实现

我目前的解决方案是请求bundle标识符并检查结果。如果是nil,我将调用
[NSBundle allBundles]
并对其进行迭代,直到找到一个具有非nil bundleIdentifier的bundleIdentifier。虽然目前。。。作品A)不太健壮B)可怕的暴力,C)修改应用程序代码以支持单元测试


是否有其他人遇到过这种情况并提出了更好的解决方案?

运行时运行正常。模拟对象是NSProxy的一个子类,因此,对象的
isa
和捆绑包之间的运行时绑定被有效地打破(特别是,
isa
指向
,然后通过
dyld
API查找该类,以确定从中加载并用于查找捆绑包的马赫-o图像)

OCMockObject
代理(或子类
OCPartialMockObject
)上可能有API,允许您检索原始类。当然,您必须使用API,这意味着您将用模拟调用污染代码,而模拟调用只应在测试中使用


或者,在bundle/framework/中返回类的bundle的任何类上实现一个类方法。这不应该被模拟。

Bill和往常一样正确。但是,我们正在更改模拟对象的行为,以便它能够完成您所期望的。这是正在进行的工作。请参阅和NSProxy subclasses typically implement-isKindOfClass:为代理的类返回YES,OCClassMockObject也不例外(尽管它可能也应该实现-class,就像NSProxy子类通常一样)。但这里的问题在于被模拟的原始对象本身——部分模拟过程改变了它的“isa”指针,因此-class方法的返回值是不同的,这反过来会弄乱bundleForClass:。但正如Erik所说,这似乎应该在OCMock的下一个版本中修复。@Carlindberg感谢您的澄清;之前我没有看过OCMock*的实现。
(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