objective-c unit-testing mocking class-method ocmock

Objective C & OC Mock: ¿burlarse de un método de clase?



objective-c unit-testing (4)

Un enfoque es envolver el método de clase en un método en su propia clase. Entonces, digamos que su clase tiene que llamar a [SomeOtherClass classMethod:someString] . Puede crear un método invokeClassMethod: en su clase de esta manera:

-(NSString *)invokeClassMethod:(NSString *)someString { return [SomeOtherClass classMethod:someString]; }

Luego, en su prueba, crea un simulacro parcial y espera invokeClassMethod:

-(void)testSomething { id partialMock = [OCMockObject partialMockForObject:actual]; [[[partialMock expect] andReturn:@"foo"] invokeClassMethod:@"bar"]; [actual doSomething:@"bar"]; [partialMock verify]; }

Si desea verificar que invokeClassMethod no se invokeClassMethod , puede lanzar una excepción:

-(void)testSomethingElse { id partialMock = [OCMockObject partialMockForObject:actual]; [[[partialMock stub] andThrow:[NSException exceptionWithName:@"foo" reason:@"Should not have called invokeClassMethod:" userInfo:nil] invokeClassMethod:OCMOCK_ANY]; [actual doSomething:@"bar"]; }

La excitación causará que la prueba falle si se llama a invokeClassMethod .

Necesito poder determinar si se llamó o no un método de clase. ¿Cómo puedo hacer esto con OCMock?


A partir de la versión 2.1 de OCMock, esto se admite de fábrica. Ahora puede anclar los métodos de clase de la misma forma que los métodos de instancia de stub.


Alternativamente, supongamos que tienes la clase:

@interface ABCCleverClass : NSObject + (id)specialMethod; @end

y quieres burlarte de este método de clase Una opción es crear una categoría en esta clase que defina e implemente el soporte de pruebas. Luego, puede cambiar la implementación del método de clase en la clase bajo prueba con su simulacro de la categoría.

#import <objc/runtime.h> @interface ABCCleverClass (TestSupport) + (id)mockSpecialMethod; @end @implementation ABCCleverClass (TestSupport) + (void)load { Method original = class_getClassMethod([ABCCleverClass class], @selector(specialMethod)); Method mocked = class_getClassMethod([ABCCleverClass class], @selector(mockSpecialMethod)); method_exchangeImplementations(original, mocked); } + (id)mockSpecialMethod { // Perform mock method. You may need to add more class methods // in order to configure this. } @end


Como Zneak mencionó en su comentario a su pregunta, eche un vistazo a esta respuesta ,

Y a partir de los comentarios de allí, revise esta implementación basada en bloques de swizzling de clase.

OCMock no parece apoyar directamente lo que quieres hacer, pero esta solución es bastante buena!