Jon*_*eid 7 objective-c objective-c-runtime class-method nsproxy
在OCMockito中,使用NSProxy实现测试双精度.实例中的双重实现-respondsToSelector:如下:
- (BOOL)respondsToSelector:(SEL)aSelector {
return [_mockedClass instancesRespondToSelector:aSelector];
}
Run Code Online (Sandbox Code Playgroud)
但是对于一个类的实现-respondsToSelector:这样的双重实现:
- (BOOL)respondsToSelector:(SEL)aSelector {
return [_mockedClass respondsToSelector:aSelector];
}
Run Code Online (Sandbox Code Playgroud)
这一切都适用于32位运行时.例如,如果_mockedClass是[NSString class],则代理正确回答它响应选择器+pathWithComponents:
但在64位运行时,它崩溃了:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: EXC_I386_GPFLT
Application Specific Information:
objc[1868]: GC: forcing GC OFF because OBJC_DISABLE_GC is set
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libobjc.A.dylib 0x00007fff95cbffc6 cache_getImp + 6
1 libobjc.A.dylib 0x00007fff95ccd1dc lookUpImpOrForward + 50
2 libobjc.A.dylib 0x00007fff95ccd198 lookUpImpOrNil + 20
3 libobjc.A.dylib 0x00007fff95cc218a class_respondsToSelector + 37
4 com.apple.CoreFoundation 0x00007fff91c131ad ___forwarding___ + 429
5 com.apple.CoreFoundation 0x00007fff91c12f78 _CF_forwarding_prep_0 + 120
6 org.mockito.OCMockitoTests 0x000000010451a55b -[StubClassTest testStubbedMethod_ShouldReturnGivenObject] + 107 (StubClassTest.m:48)
Run Code Online (Sandbox Code Playgroud)
请注意,它正在呼叫class_respondsToSelector(…).我怀疑我被运行时的优化所困扰.我该怎么做才能解决这个问题?
这是一个有点长的答案,所以忍受我.我运行了一个简单的代码来验证行为:
Class mock = mockClass([NSProcessInfo class]);
[mock processInfo];
[verify(mock) processInfo];
Run Code Online (Sandbox Code Playgroud)
确实它会因为错误的指针异常而崩溃.用.替换第一行
id mock = mockClass([NSProcessInfo class]);
Run Code Online (Sandbox Code Playgroud)
按预期工作.我认为在ARC之后查看代码可能是值得的.那些片段有点长,所以这里有一些要点:Class基于测试,id基于测试
正如您所看到的,当您声明类型变量时,Class会有额外的变量release.我的猜测是,因为类在整个运行时间内注册(除非使用运行时api删除),所以可以将Class变量设置为__unsafe_unretained.
总而言之,您有两种可能的解决方案:
@implementation StubClassTest
{
__strong Class mockClass;
}
Run Code Online (Sandbox Code Playgroud)
要么
@implementation StubClassTest
{
id mockClass;
}
Run Code Online (Sandbox Code Playgroud)
似乎为我解决了这个问题.
更新
作为一种特殊情况,如果对象的基类型是Class(可能是协议限定的),则将类型调整为具有__unsafe_unretained限定.
来自http://clang.llvm.org/docs/AutomaticReferenceCounting.html#objects
| 归档时间: |
|
| 查看次数: |
1122 次 |
| 最近记录: |