xcode primitive ocmock

xcode - Pasando primitivas a un código auxiliar de OCMock



primitive (6)

Estoy aprendiendo a usar OCMock para probar el proyecto de mi iPhone y tengo este escenario: una clase de HeightMap con un getHeightAtX:andY: y una clase de Render que usa HeightMap . Estoy tratando de hacer una prueba de unidad de Render con algunas HeightMap . Esto funciona:

id mock = [OCMockObject mockForClass:[Chunk class]]; int h = 0; [[[mock stub] andReturnValue:OCMOCK_VALUE(h)] getHeightAtX:0 andY:0];

Por supuesto, funciona solo para x=0 y y=0 . Quiero probar usando un mapa de altura "plano". Esto significa que necesito hacer algo como esto:

id chunk = [OCMockObject mockForClass:[Chunk class]]; int h = 0; [[[chunk stub] andReturnValue:OCMOCK_VALUE(h)] getHeightAtX:[OCMArg any] andY:[OCMArg any]];

Pero esto plantea dos advertencias de compilación:

advertencia: pasar el argumento 1 de ''getHeightAtX:andY:'' hace un entero desde el puntero sin una ''getHeightAtX:andY:''

y un error de ejecución:

método inesperado invocado: ''getHeightAtX:0 andY:0 stubbed: getHeightAtX:15545040 andY:15545024''

¿Qué me estoy perdiendo? No encontré ninguna manera de pasar un valor anyValue a este simulacro.


A pesar de ser bastante intrépido, el enfoque de usar las expectativas para almacenar el bloque aprobado para llamar más tarde en el código de prueba me ha funcionado:

- (void)testVerifyPrimitiveBlockArgument { // mock object that would call the block in production id mockOtherObject = OCMClassMock([OtherObject class]); // pass the block calling object to the test object Object *objectUnderTest = [[Object new] initWithOtherObject:mockOtherObject]; // store the block when the method is called to use later __block void (^completionBlock)(NSUInteger value) = nil; OCMExpect([mockOtherObject doSomethingWithCompletion:[OCMArg checkWithBlock:^BOOL(id value) { completionBlock = value; return YES; }]]); // call the method that''s being tested [objectUnderTest doThingThatCallsBlockOnOtherObject]; // once the expected method has been called from `doThingThatCallsBlockOnOtherObject`, continue OCMVerifyAllWithDelay(mockOtherObject, 0.5); // simulate callback from mockOtherObject with primitive value, can be done on the main or background queue completionBlock(45); }


Además de la respuesta de Andrew Park , podría hacerlo un poco más general y de aspecto agradable:

#define OCMStubIgnoringNonObjectArgs(invocation) / ({ / _OCMSilenceWarnings( / [OCMMacroState beginStubMacro]; / [[[OCMMacroState globalState] recorder] ignoringNonObjectArgs]; / invocation; / [OCMMacroState endStubMacro]; / ); / })

Puedes usarlo así:

OCMStubIgnoringNonObjectArgs(someMethodParam:0 param2:0).andDo(someBlock)

Puedes hacer lo mismo por esperar. Este caso es para el apéndice como solicitud de inicio de tema. Fue probado con OCMock 3.1.1.


Ha pasado un tiempo desde que se hizo esta pregunta, pero me encontré con este problema y no pude encontrar una solución en ninguna parte. OCMock ahora admite ignorarNonObjectArgs, por lo que un ejemplo de expect sería

[[[mockObject expect] ignoringNonObjectArgs] someMethodWithPrimitiveArgument:5];

El 5 en realidad no hace nada, solo un valor de relleno.


OCMock no admite actualmente la concordancia suelta de argumentos primitivos. Existe una discusión sobre posibles cambios para admitir esto en los foros de OCMock , aunque parece haberse estancado.

La única solución que he encontrado es estructurar mis pruebas de tal manera que conozca los valores primitivos que se transmitirán, aunque está lejos de ser lo ideal.



Utilice OCMockito en OCMockito lugar.

Es compatible con la coincidencia de argumentos primitivos.

Por ejemplo, en su caso:

id chunk = mock([Chunk class]); [[given([chunk getHeightAtX:0]) withMatcher:anything() forArgument:0] willReturnInt:0];