unit-testing ocmock

unit testing - ¿Cómo se puede cambiar el valor de retorno de un código auxiliar OCMock?



unit-testing (4)

Aunque creo que CipherCom tiene la respuesta correcta, prefiero crear una clase auxiliar para devolver varios valores. He tenido problemas con NSInvocation en el pasado.

@interface TestHelper : NSObject @property (nonatomic, assign) CGPoint velocity; - (CGPoint)getCurrentVelocity; @end @implementation TestHelper - (CGPoint)getCurrentVelocity { return self.velocity; } @end

Luego, en mi clase de prueba tendría una variable miembro privada para TestHelper y en el método de setUp haría:

self.testHelper = [TestHelper new]; [[[physics stub] andCall:@selector(getCurrentVelocity) onObject:self.testHelper] getCurrentVelocity];

De esa manera, en cada una de mis pruebas podría establecer la velocidad a lo que quiero para la prueba.

self.testHelper.velocity = CGPointMake(100, 200);

Parece que la primera vez que agrego andReturnValue en un código auxiliar OCMock, ese valor de retorno se establece en piedra. Por ejemplo:

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];

El método de código auxiliar se llama en [testEntity update]. Pero cada vez que el método stubbed devuelve el valor de velocidad1, por lo que supongo que el segundo intento de establecer el valor de retorno de los métodos no se cumple.

¿Hay alguna manera de hacer esto en OCMock?


Cuando stub un método, estás diciendo que siempre debería funcionar de la manera especificada, sin importar cuántas veces se llame. La forma más fácil de solucionar esto es cambiar el stub que se 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];

Alternativamente, si necesita stub (por ejemplo, si no se puede llamar al método en absoluto), puede volver a crear el simulacro:

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];


En realidad, cuando stub solo estás configurando el valor de retorno en piedra si utilizas andReturn andReturnValue . Puede usar el método andDo para cambiar el valor devuelto cuando lo desee. Esta es una mejora con respecto a la expect en la que necesita saber cuántas veces se llamará un método. Aquí el fragmento de código para lograr esto:

__weak TestClass *weakSelf = self; [[[physics stub] andDo:^(NSInvocation *invocation) { NSValue *result = [NSValue valueWithCGPoint:weakSelf.currentVelocity]; [invocation setReturnValue:&result]; }] getCurrentVelocity];


Parece que ni andReturn / andReturnValue / andDo no se anula cuando se llama varias veces. Mi solución fue agregar una propiedad a la clase de prueba y usarla para controlar lo que debería devolver el objeto simulado. Por ejemplo, en caso de una propiedad isAvailable en un objeto isAvailable , mi código se vería así:

@interface MyTest: XCTestCase @property BOOL stubbedIsAvailable; @end @implementation MyTest - (void)setUp { [OCMStub([myMockedObject isAvailable]) andDo:^(NSInvocation invocation) { BOOL retVal = self.stubbedIsAvailable; [invocation setReturnValue:&retVal]; } } - (void)testBehaviourWhenIsAvailable { self.stubbedIsAvailable = YES; // test the unit } - (void)testBehaviourWhenIsNotAvailable { self.stubbedIsAvailable = NOT; // test the unit }