OCMockはXcode標準のテスト環境でも利用可能なモックライブラリです。 OCMockを利用すると他のクラス実装に依存しないようなテストを簡単に書くことができるようになります。
そこで、本記事ではOCMockを導入して、プロジェクトに必要な設定を行う方法とOCMockの簡単な利用法について紹介します。なお、利用環境はOS X 10.6.8, Xcode 4.2, OCMock 2.0.1です。
OCMockの簡単な利用法
まずはOCMockの簡単な利用法について少しだけ紹介します。 概要についてはFeatures - OCMockがより詳しいです。
stub
テストで未実装なクラスや外部サーバに依存するようなクラスを利用しなければならず、 とりあえずそれっぽい値を返すようにさせたいときに、stubが使えます。
id mock = [OCMockObject mockForClass:[SampleClass class]]; [[[mock stub] andReturn:@"foobar"] someMethod:@"FOOBAR"];
これで、+someMethod:に引数@"FOOBAR"を指定したときに@"foobar"を返すようなSampleClassのモックが利用可能になります。
STAssertEqualObjects(@"foobar", [mock someMethod:@"FOOBAR"], @"tolower");
この呼び出しは複数登録することができます。
[[[mock stub] andReturn:@"hoge"] someMethod:@"HOGE"]; STAssertEqualObjects(@"hoge", [mock someMethod:@"HOGE"], @"tolower");
ただし、未登録の引数で呼び出すとunexpected method invokedとなります。
STAssertEqualObjects(@"fuga", [mock someMethod:@"FUGA"], @"tolower"); // unexpected method invoked: someMethod:@"FUGA"
引数が何でもいいという場合にはOCMArgの+anyが利用できます。
[[[mock stub] andReturn:@"*ANY*"] someMethod:[OCMArg any]];
mock
mockを用いると、「これをしたら、あれが呼ばれるはず」というのがテストできます。
次の例はOCMockのソース内のiOS5ExampleTestsにあるコードで、「UITableViewCellEditingStyleDeleteを指定して
-tableView:commitEditingStyle:forRowAtIndexPath:を呼んだら
-deleteRowsAtIndexPaths:withRowAnimation:が呼ばれるはず」というのをテストしています。
- (void)testMasterViewControllerDeletesItemsFromTableView {
MasterViewController *controller = [[MasterViewController alloc] init];
NSIndexPath *dummyIndexPath = [NSIndexPath indexPathWithIndex:3];
id tableViewMock = [OCMockObject mockForClass:[UITableView class]];
[[tableViewMock expect] deleteRowsAtIndexPaths:[NSArray arrayWithObject:dummyIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
[controller tableView:tableViewMock
commitEditingStyle:UITableViewCellEditingStyleDelete
forRowAtIndexPath:dummyIndexPath];
[tableViewMock verify];
}
これら以外にもプロトコルのためのモック (mockForProtocol) や、 既存インスタンスの部分的振る舞いを変更できるモック (partialMockForObject) などが利用できます。
なお、テスト結果はLog Nagigator (XcodeでCmd + 7) で見ることができます。
導入とプロジェクト設定
iOS 5 - OCMockを参考にプロジェクトSampleにOCMockを導入します。
Download - OCMockからOCMock 2.0のdmgをダウンロード
dmgをマウントして、次のようにしてライブラリをコピー
cp -r /Volumes/OCMock\ 2.0.1/iOS ~/src/ocmock-iosターゲットSampleTestのLink Binary with LibrariesにlibOCMock.aを追加
Header Search Pathに$HOME/src/ocmock-iosを追加
Other Linker Flagsに-force_loadと$HOME/src/ocmock-ios/libOCMock.aと-ObjCを追加
-force_loadの引数が$HOME/src/ocmock-ios/libOCMock.aになっているので順番に気をつけること
なお、Other Linker Flagsでの指定の話題は次の項目を参照してください。 簡単に言うと既存クラスへの追加カテゴリを含む静的ライブラリをリンクすると実行時例外 “selector not recognized” が発生するので、その回避のための手段です。
- Cocoaの日々: Static Library (7) カテゴリを使う場合の注意点 “-ObjC” と “-all_load”
- Technical Q&A QA1490: Technical Q&A QA1490
まとめ
OCMockを導入してプロジェクト設定を行う方法とOCMockの簡単な利用法について紹介しました。

0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。