ios - ¿Puede OCMock ejecutar un parámetro de bloque?
unit-testing (5)
Supongamos una firma de método como la siguiente:
- (void)theMethod:(void(^)(BOOL completed))completionBlock;
Me gustaría burlarme de esta firma de método para asegurar que se llame al método, y simplemente llamar al bloque de finalización. Veo en otras publicaciones como esta que puedo burlarme de la llamada al método y aceptar cualquier bloque, pero no ejecutar el bloque. También sé que hay un método andDo que puedo usar, pero no sé cómo pasar un bloque y ejecutarlo.
¿Algunas ideas?
Gracias.
EDITAR 2: Use https://.com/a/32945785/637641 lugar.
Usar andDo:
está perfectamente bien, pero personalmente prefiero [OCMArg checkWithBlock:]
.
[[mock expect] theMethod:[OCMArg checkWithBlock:^BOOL(id param)
{
void (^passedBlock)( BOOL ) = param;
// Normally I set some expectations here and then call the block.
return YES;
}]];
// Code to test
[mock verify];
También puede usar [simulacro de código auxiliar] pero prefiero verificar que se llame al Método.
EDITAR 1
Versión OCMock 3:
OCMExpect([mock theMethod:[OCMArg checkWithBlock:^BOOL(void (^passedBlock)(BOOL))
{
// call the block...
return YES;
}]]);
// Code to test
OCMVerify(mock);
El uso de los bloques andDo:
veces es necesario, pero en la mayoría de los casos puede usar [OCMArg invokeBlock]
o [OCMArg invokeBlockWithArgs:]
.
En tu ejemplo puedes hacer lo siguiente
Si no te importan los argumentos:
// Call block with default arguments.
OCMStub([mock theMethod:[OCMArg invokeBlock]];
Si quieres enviar argumentos específicos:
// Call block with YES.
OCMStub([mock theMethod:([OCMArg invokeBlockWithArgs:@YES, nil])];
Tenga en cuenta la terminación nil
ya que puede pasar varios argumentos a este método. Además, toda la expresión debe estar entre paréntesis.
Puedes leer más sobre esto en la documentación de OCMock .
Esta es la respuesta de Sven actualizada para OCMock 3.
OCMStub([myMock myMethodWithMyBlock:[OCMArg any]]).andDo(^(NSInvocation *invocation) {
void (^passedBlock)(BOOL myFirstArgument, NSError *mySecondArgument);
[invocation getArgument: &passedBlock atIndex: 2];
passedBlock(YES, nil);
});
Esto ahora es compatible con OCMock 3.2. Puede usar [OCMArg invokeBlock]
y [OCMArg invokeBlockWithArgs:...]
para invocar el bloque pasado como un argumento a un método de apéndice.
Puede usar [[mock stub] andDo:]
esta manera para pasar otro bloque al que se llama cuando se llama a su método [[mock stub] andDo:]
:
void (^proxyBlock)(NSInvocation *) = ^(NSInvocation *invocation) {
void (^passedBlock)( BOOL );
[invocation getArgument: &passedBlock atIndex: 2];
};
[[[mock stub] andDo: proxyBlock] theMethod:[OCMArg any]];
El bloque obtiene una instancia de NSInvocation
desde la que puede consultar todos los argumentos utilizados. Tenga en cuenta que el primer argumento está en el índice 2, ya que tiene self y _cmd en los índices 0 y 1.