2013-04-11 7 views
1

단위 테스트에서 OCMocks를 사용하는 법을 배우고 있으며 기본을 이해합니다. 그러나 클래스 메서드에 대한 호출을 모의 할 수있는 방법이 확실하지 않습니다.OCMock을 사용하여 모의하기 [[UIDevice currentDevice] userInterfaceIdiom]

내가 갖고 싶은 것 : 내 테스트 케이스에 대한

[[UIDevice currentDevice] userInterfaceIdiom] 

반환 다른 (그러나 유효) 인터페이스 숙어.

id mock = [OCMockObject mockForClass:[UIDevice class]]; 

// Would I use a mock or a stub to have UIDevice mock return 
// currentDevice and then from it, return userInterfaceIdiom 

답변

2

조롱하는 것은 까다 롭습니다. 일부 런타임 마술로 할 수 있습니다. Matt Gallagher's invokeSupersequent macro의 도움으로 가능합니다. 기본적으로 모의 객체를 설정 한 경우에만 currentDevice을 오버라이드하여 모의 객체를 반환하는 카테고리를 테스트 케이스에 추가합니다. 여기 설치는 다음과 같습니다

#import "NSObject+SupersequentImplementation.h" 

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation" 

@implementation UIDevice (UnitTests) 

+(id)currentDevice { 
    if ([BaseTestCase mockDevice]) { 
     return [BaseTestCase mockDevice]; 
    } 

    return invokeSupersequentNoArgs(); 
} 

@end 

#pragma clang diagnostic pop 


static id mockDevice = nil; 

+(id)mockDevice { 
    return mockDevice; 
} 

+(id)createMockDevice { 
    mockDevice = [OCMockObject mockForClass:[UIDevice class]]; 
    return mockDevice; 
} 

+(id)createNiceMockDevice { 
    mockDevice = [OCMockObject niceMockForClass:[UIDevice class]]; 
    return mockDevice; 
} 

-(void)tearDown { 
    mockDevice = nil; 
    [super tearDown]; 
} 

를 그런 다음 테스트 :

-(void)testShouldDoSomethingOnIpad { 
    id mockDevice = [BaseTestCase createNiceMockDevice]; 
    [[[mockDevice stub] andReturnValue:OCMOCK_VALUE(UIUserInterfaceIdiomPad)] userInterfaceIdiom]; 

    // do something iPad-specific 

    [mockDevice verify]; 
} 

내가 잠시 다시 more detailed write-up of this approach했다.

+0

[UIDevice currentDevice].userInterfaceIdiom 

이 주셔서 감사합니다이 검사를 사용하고 있는지 확인하십시오 : 여기
-(void)testShouldDoSomething { if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { // test iPad behavior } else { // test iPhone behavior } } 

+0

때때로 테스트의 일부가 'UIDevice'속성을 호출하는 부작용이 있습니다. 좋은 모의를 사용하지 않고 시작하고 필요한 경우 좋은 것을 위해 그것을 사용할 수 있습니다. 그것은 모두 당신이 테스트하고 얼마나 많은 "진짜"행동을 허용하고 싶어하는지에 달려 있습니다. –

0

다른 대안은 두 변종을 테스트에 넣고 iPhone 및 iPad 시뮬레이터에서 테스트를 실행하는 것입니다. 틀림없이, 이것은 약간 번거 롭다.

OCMockObject* _deviceMock = OCMPartialMock([UIDevice currentDevice]); 

[[[_deviceMock stub] andReturnValue:@(UIUserInterfaceIdiomPad)] userInterfaceIdiom]; 

그냥 당신의 행동의 코드 대신 매크로

UI_USER_INTERFACE_IDIOM() 
+0

이것이 최선의 해결책이라고 생각합니다. 테스트는 두 장치 모두에서 실행되어야합니다. – Sulthan

3

간단한 해결책이다 당신의 대답과 엄청나게 도움이되는 글. 선행 노력에도 불구하고, 나는이 솔루션이 테스트에 더 좋다고 생각한다. 일반적인 모의와 반대로 niceMock을 사용하는 이유는 무엇입니까?