Search code examples
iosuiviewcontrollerocunitocmock

Adding a root view controller OCMockObject[UIViewController] as a child view controller error


I've been working on my unit tests for iOS programming, and I've run into a little problem when trying to validate my main class by mocking it's child classes using OCMock and then seeing if the main class adds the child controllers (mockObjects[uiviewContoller]) and then verifying that an object calls a method on each of the child controllers.

The problem is I keep getting a "test failed 'adding a root view controller OCMockObject[UiViewController] as a child of view controller'"

every other time i run the test.

   - (void)setUp
{
    [super setUp];
     testMain = [[UIViewController alloc] init];
}

- (void)tearDown
{
    for (UIViewController *testCon in testMain.childViewControllers) {
        [testCon removeFromParentViewController];
    }
    testMain = nil;
    [super tearDown];
}

test:

- (void) testDayNightTriggerTriggersAllSubviews{
    id mockTopController = [OCMockObject niceMockForClass:[UIViewController class]];
    id mockBottomController = [OCMockObject niceMockForClass:[UIViewController class]];
    id mockMainScreen = [OCMockObject niceMockForClass:[UIViewController class]];

    [[mockTopController expect] dayNightTrigger];
    [[mockBottomController expect] dayNightTrigger];
    [[mockMainScreen expect] dayNightTrigger];

    //trigger

     [testMain dayNightTrigger:mockTopController bottom:mockBottomController main:mockMainScreen];

    [mockBottomController verify];
    [mockTopController verify];
    [mockMainScreen verify];

}

Method to verify:

//overload
- (void) dayNightTrigger:(UIViewController *) top bottom:(UIViewController *)bottom main:(UIViewController *)main{
    self.bottomMenu = bottom;
    self.topMenu = top;
    self.mainScreen = main;
    [self dayNightTrigger];
}
- (void) dayNightTrigger{
    [self.app dayNightTrigger];

    [self.bottomMenu dayNightTrigger];
    [self.topMenu dayNightTrigger];
    [self.mainScreen dayNightTrigger];
}

I was wondering if there is anything wrong with my setup/teardown? or I'm doing something wrong with the OCMock framework, but really as to why I keep getting this error.


Solution

  • I've run into the same issue. I'm guessing that your properties bottomMenu, topMenu, and mainScreen set bottom, top, and main as child view controllers of the other view controller.

    Unfortunately, addChildViewController: looks at some value in the UIViewController* structure. Since it's a direct memory access and not a method call, the OCMockObject can't intercept it. As a result, the mock object is (sometimes) treated as being a root view.

    The way I found around it was to override addChildViewController: on the object I was testing in the test file and have it do nothing:

    @implementation MyViewController (overwriteForTesting)
    - (void)addChildViewController:(UIViewController *)childController {
    }
    @end
    

    This means that it won't add the view controller to its list of children though.