How can the return value of an OCMock stub be changed?

Cris picture Cris · Apr 14, 2011 · Viewed 12.1k times · Source

It seems that the first time I add andReturnValue on an OCMock stub, that return value is set in stone. For example:

id physics = [OCMockObject niceMockForClass:[DynamicPhysicsComponent class]
Entity *testEntity = [Entity entityWithPhysicsComponent:physics];
CGPoint velocity1 = CGPointMake(100, 100);
CGPoint velocity2 = CGPointZero;
[[[physics stub] andReturnValue:OCMOCK_VALUE(velocity1)] getCurrentVelocity];
[testEntity update:0.1];
[[[physics stub] andReturnValue:OCMOCK_VALUE(velocity2)] getCurrentVelocity];
[testEntity update:0.1];

The stubbed method is called in [testEntity update]. But each time the stubbed method is returning the velocity1 value, so I guess the second attempt to set the methods return value isn't honoured.

Is there a way to do do this in OCMock?

Answer

Christopher Pickslay picture Christopher Pickslay · Apr 14, 2011

When you stub a method, you're saying it should always function in the specified way, no matter how many times it's called. The easiest way to fix this is to change stub to expect:

CGPoint velocity1 = CGPointMake(100, 100);
CGPoint velocity2 = CGPointZero;
[[[physics expect] andReturnValue:OCMOCK_VALUE(velocity1)] getCurrentVelocity];
[testEntity update:0.1];
[[[physics expect] andReturnValue:OCMOCK_VALUE(velocity2)] getCurrentVelocity];
[testEntity update:0.1];

Alternatively, if you need to stub (for example if the method might not be called at all), you can just re-create the mock:

CGPoint velocity1 = CGPointMake(100, 100);
CGPoint velocity2 = CGPointZero;
[[[physics stub] andReturnValue:OCMOCK_VALUE(velocity1)] getCurrentVelocity];
[testEntity update:0.1];
[physics verify];

physics = [OCMockObject mockForClass:[Physics class]];
[[[physics stub] andReturnValue:OCMOCK_VALUE(velocity2)] getCurrentVelocity];
[testEntity update:0.1];
[physics verify];