어느 개발자의 한적한 공간 살아나가면서 저지른 이야기

OCMock을 통한 간단한 테스트 케이스 작성

OCMock을 통한 간단한 테스트 케이스 작성과 원리 그 동안 간단한 모델 로직만 테스트 케이스를 작성했었는데 OCMock을 통해서 mock객체를 만들고 테스트를 작성하는 법을 배웠다.

@property (nonatomic, strong) id textField;
@property (nonatomic, strong) id fahrenheitLabel;
@end
@implementation TestConverter
@synthesize textField;
@synthesize fahrenheitLabel;

- (void)setUp {
     [super setUp];
     textField = [OCMockObject mockForClass: [UITextField class]];
     fahrenheitLabel = [OCMockObject mockForClass: [UILabel class]];
}

- (void)testThatMinusFortyCelsiusIsMinusFortyFahrenheit {
     [[[textField stub] andReturn: @"-40"] text];
     [[fahrenheitLabel expect] setText: @"-40"];
     [self convertToFahrenheit: textField];
     [fahrenheitLabel verify];
     [textField verify];
}

- (void)tearDown {
     [super tearDown];
}
@end

테스트 케이스 메서드는 모의 객체에게 테스트 동안 무엇이 일어나야 하는지 알려준다. 모의 UITextField에게 -text 메서드를 호출했을 때 문자열 @“-40”을 반환하게 지시한다. OCMock은 메서드를 뒤섞어서 이를 가능하게 한다. -stub을 호출하는 것은 실제 -[UITextField text] 구현을 테스트에서 지정한 값을 반환하는 스텁 메서드로 대체한다. UILabel 모의 객체에 대한 -expect 호출은 부가 작용이 레이블의 -setText를 호출하고 매개변수가 @“-40”이 되는 것이어야 함을 OCMock에게 알려준다.

주어진 값을 반환하는 스텁으로 메서드를 바꾸고 모의 객체에서 부르는 메서드에 대한 기대값을 표현하는 모의 객체의 기능이 모의 객체로 만든 클래스와는 무관하다는 것에 주목하자. OCMock은 모의로 만든 클래스의 동작을 찾고 교체하려고 오브젝티브C 실시간 라이브러리를 사용한다. 그래서 이 테스트는 UIKit 객체만을 이용한 사용버을 보여줬지만 직접 만든 클래스를 포함한 어떤 클래스라도 OCMock을 사용할 수 있다.

테스트에 더이상 어써트 매크로가 존재하지 않는다. OCMock은 테스트 메서드의 마지막에 -verify 호출을 사용해 부가작용의 결과를 테스트하기 때문이다. 그리고 -convertToFahrenheit: 메서드가 값을 반환하지 않기 때문에 이외에 더 할 것은 없다. 좀더 복잡한 테스트에서는 예상한 이벤트가 모두 발생했다는 것을 보장하려고 모든 모의 객체에 대해 -verify를 호출할 필요가 있다. 이번에 OCMock은 레이블의 문자를 올바르게 설정했는지와 아무 일도 발생하지 않았는지를 검사한다. 기대를 충족시키지 못했다면 OCMock은 해당 문제를 설명하는 예외를 발생시킨다.

출처 : “테스트 주도 iOS 애플리케이션 개발”, 2013, 에이콘

iOS 개발 #iOS #OCMock #test #tip