7

OCMockito では、テスト ダブルは NSProxy で実装されます。インスタンスのダブル スタンディングは次のように実装さ-respondsToSelector:れます。

- (BOOL)respondsToSelector:(SEL)aSelector {
    return [_mockedClass instancesRespondToSelector:aSelector];
}

しかし、クラスのダブル スタンディングは次の-respondsToSelector:ように実装されます。

- (BOOL)respondsToSelector:(SEL)aSelector {
    return [_mockedClass respondsToSelector:aSelector];
}

これはすべて 32 ビット ランタイムで機能します。たとえば、_mockedClassis[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)

を呼び出していることに注意してくださいclass_respondsToSelector(…)。ランタイムに加えられた最適化に噛まれているのではないかと思います。これを修正するにはどうすればよいですか?

4

1 に答える 1

7

少し長い答えなので、我慢してください。動作を確認するためだけに簡単なコードを実行しました。

Class mock = mockClass([NSProcessInfo class]);
[mock processInfo];
[verify(mock) processInfo];

確かに、不良ポインター例外でクラッシュします。最初の行を次のように置き換えます

id mock = mockClass([NSProcessInfo class]);

期待どおりに動作します。ARC の後のコードを見る価値があるかもしれないと考えました。これらのスニペットは少し長すぎるので、ここに要点を示します: Class-based testid-based test

ご覧のとおり、型の変数を宣言するClassと、extra がありreleaseます。私の推測では、クラスはランタイム全体にわたって登録されるため (ランタイム API を使用して削除されない限り)、Class変数を__unsafe_unretained.

要約すると、考えられる解決策は 2 つあります。

@implementation StubClassTest
{
    __strong Class mockClass;
}

また

@implementation StubClassTest
{
    id mockClass;
}

私の問題を解決しているようです。

アップデート

特殊なケースとして、オブジェクトの基本型がクラス (おそらくプロトコル修飾) の場合、型は代わりに __unsafe_unretained 修飾を持つように調整されます。

http://clang.llvm.org/docs/AutomaticReferenceCounting.html#objectsから

于 2014-05-28T13:23:40.847 に答える