Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to init an object with stubbed values with OCMock

Ho do I stub a method used in the init method?

The related methods in my class:

- (id)init
{
    self = [super init];
    if (self) {
        if (self.adConfigurationType == AdConfigurationTypeDouble) {
             [self configureForDoubleConfiguration];
        }
        else {
            [self configureForSingleConfiguration];
        }
    }
    return self;
}

- (AdConfigurationType)adConfigurationType
{
    if (adConfigurationType == NSNotFound) {
        if ((random()%2)==1) {
            adConfigurationType = AdConfigurationTypeSingle;
        }
        else {
            adConfigurationType = AdConfigurationTypeDouble;
        }
    }
    return adConfigurationType;
}

My test:

- (void)testDoubleConfigurationLayout
{
    id mockController = [OCMockObject mockForClass:[AdViewController class]];
    AdConfigurationType type = AdConfigurationTypeDouble;
    [[[mockController stub] andReturnValue:OCMOCK_VALUE(type)] adConfigurationType];

    id controller = [mockController init];

    STAssertNotNil([controller smallAdRight], @"Expected a value here");
    STAssertNotNil([controller smallAdRight], @"Expected a value here");
    STAssertNil([controller largeAd], @"Expected nil here");
}

My result:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'OCMockObject[AdViewController]: unexpected method invoked: smallAdRight '

So how will I access the AdViewController in the OCMockObject?

like image 939
mOp Avatar asked Sep 14 '11 09:09

mOp


1 Answers

If you use the mockForClass: method you will need to provided stubbed implementations for each and every method that are called in the mocked class. including your call into it with [controller smallAdRight] in your first test.

Instead you can use the niceMockForClass: method which will just ignore any messages which are not mocked.

Another alternative is to instantiate your AdViewController and then create a partial mock for it using the partialMockForObject: method. This way the internals of the controller class will do the main part of the work.

Just a though... are you trying to test the AdViewController or a class which uses it? It appears that you are trying to mock the entire class and then test if it still behaves normally. If you want to test that AdViewController behaves as expected when certain values are injected then your best option is most likely the partialMockForObject: method:

- (void)testDoubleConfigurationLayout {     
  AdViewController *controller = [AdViewController alloc];
  id mock = [OCMockObject partialMockForObject:controller];
  AdConfigurationType type = AdConfigurationTypeDouble;
  [[[mock stub] andReturnValue:OCMOCK_VALUE(type)] adConfigurationType];

  // You'll want to call init after the object have been stubbed
  [controller init]

  STAssertNotNil([controller smallAdRight], @"Expected a value here");
  STAssertNotNil([controller smallAdRight], @"Expected a value here");
  STAssertNil([controller largeAd], @"Expected nil here");
}
like image 157
Claus Broch Avatar answered Sep 24 '22 17:09

Claus Broch