9

OCMockを使用して模擬UINavigationControllerを作成しました。ただし、UIViewControllerのnavigationControllerプロパティは読み取り専用であるため、このプロパティに割り当てることはできません。

id mockNavController = [OCMockObject mockForClass:[UINavigationController class]];
...
myViewController.navigationController = mockNavController; // readonly!

このブログ投稿の作者は、解決策を見つけたと主張していますが、それを共有することを怠っています。

4

4 に答える 4

17

それを返すアクセサーをモックできるので、navigationControllerプロパティを設定できるミューテーターを作成する必要はありません。これが私がそれをする方法です:

-(void)testTappingSettingsButtonShouldDisplaySettings {
    MyController *myController = [[MyController alloc] init];

    // expect the nav controller to push a settings controller
    id mockNavigationController = [OCMockObject mockForClass:[UINavigationController class]];
    [[mockNavigationController expect] pushViewController:[OCMArg any] animated:YES];

    // set up myController to return the mocked navigation controller
    id mockController = [OCMockObject partialMockForObject:myController];
    [[[mockController expect] andReturn:mockNavigationController] navigationController];

    [myController settingsButtonTapped];

    [mockNavigationController verify];
    [mockController verify];
    [myController release];
}
于 2010-12-28T00:02:14.600 に答える
2

応答は非常に遅いですが、後世のために、これを行う別の方法は、状態ベースのアプローチを採用し、実際にテスト対象のビューコントローラーを実際のナビゲーションコントローラーに固定することです。次に、ビューコントローラを調べて、ナビゲーションコントローラの状態を調べることにより、ナビゲーションスタックで何が行われるかをテストできます。次に例を示します。

it(@"displays the station chooser when you tap the 'Choose station' button", ^{
    // Given
    LaunchViewController *launchViewController = [LaunchViewController newWithNearestStationLocator:nil];
    [launchViewController view];
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:launchViewController];

    // When
    [[launchViewController chooseStationBtn] sendActionsForControlEvents:UIControlEventTouchUpInside];

    // Then
    [[theValue(navController.viewControllers.count) should] equal:theValue(2)];
    [[NSStringFromClass(navController.visibleViewController.class) should] equal:@"StationsViewController"];
});
于 2013-12-21T05:31:17.900 に答える
0

テストで使用した手法の1つは、内部プロパティにアクセスできるように、メインクラスにメソッドを追加するカテゴリを定義することです。カテゴリを使用してセッターを合成してみることができますが、ナビゲーションコントローラーのポインターを保持する変数名を知っている必要がある場合があります。

于 2010-12-22T23:57:25.830 に答える
0

考えられる解決策がいくつかあります。

NavigationControllerのプライベートセッターを呼び出すことはできますが、それが存在しないか、すべての場合に確実に機能するとは限りません。

Derekのアドバイスに従って、UIViewControllerのnavigationControllerプロパティを再定義するカテゴリを作成できます。その場合、navigationControllerプロパティへのアクセスは安全ですが、UIViewControllerがバッキングivarに直接アクセスし、カテゴリで同じivarを使用しなかった場合、予期しない動作が発生する可能性があります。

http://blog.carbonfive.com/2010/03/10/testing-view-controllers/のように、UINavigationControllerの部分的なモックを使用できます。その場合、テストはそれほど分離されていませんが、少なくともUIViewControllerスーパークラスとUINavigationControllerのプライベートな動作は変更されていないはずです。

于 2010-12-23T21:42:30.600 に答える