OCMock のスタブandDoメソッドを使用してコード ブロックを記述しようとしています。
この場合、UIImageView 拡張クラスがテストされています。拡張機能が非 nil のパラメーターで[self setImage:]を呼び出すことを確認したい(後で他の画像比較が使用されます)。
OCMock のandDoメソッドを使用すると、ブロックの完了後に EXC_BAD_ACCESS でテストがクラッシュします。
id mockView = [OCMockObject mockForClass:[UIImageView class]];
[[[mockView stub] andDo:^(NSInvocation *invocation)
{
UIImage *img;
[invocation getArgument:&img atIndex:2]; <---- line causing the exception
somebodySetImage |= (img != nil);
}] setImage:OCMOCK_ANY];
[mockView do_something_that_calls_setImage];
私が今のところ見つけた唯一の解決策は、 andDo の代わりに andCall を使用することですが、これはテストを複雑にします。
andDoでクラッシュを回避できますか?
更新 さて、ここでより良い例を挙げようとします: これがテストコードの新しい部分です:
- (void)testDownloadingThumbnail
{
PInfo *_sut = [[PInfo alloc] init];
__block id target = nil;
id mock = [OCMockObject mockForClass:[NSOperationQueue class]];
[[[mock expect] andDo:^(NSInvocation *inv)
{
NSInvocationOperation *op;
[inv getArgument:&op atIndex:2];
target = [[op invocation] target]; /* replacing this line with STAssert does not help either */
}] addOperation:OCMOCK_ANY];
[_sut setDownloadQueue:mock];
[_sut startDownloadingImagesAsync:YES];
[mock verify];
STAssertEqualObjects(target, _sut, @"invalid op target");
}
テストされたコードは次のとおりです (PInfo からの単一のメソッド)。
- (void)startDownloadingImagesAsync:(bool)isThumbnailImg
{
NSInvocationOperation *inv;
inv = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(loadThumbnailWorker:)
object:nil];
[[self downloadQueue] addOperation:inv];
}
EXC_BAD_ACCESS を使用してstartDownloadingImagesAsyncを終了すると、コードは引き続きクラッシュします。andDoブロック内にブレークポイントを追加すると、コントロールがこのポイントに到達し、getArgumentを介して正しいオブジェクトを取得することがわかります。
それでも、ブロック内でgetArgumentを使用すると、何をしようとしてもクラッシュします。
PS助けてくれてありがとう。