문제

나는 종종 iPhone Objective-C 단위 테스트에서 클래스 메소드 (예 : nsurlconnection의 +sendsynchronousRequest : returningResponse : error : method.

단순화 된 예 :

- (void)testClassMock
{
    id mock = [OCMockObject mockForClass:[NSURLConnection class]];
    [[[mock stub] andReturn:nil] sendSynchronousRequest:nil returningResponse:nil error:nil];
}

이것을 실행할 때 : 나는 다음을 얻는다 :

Test Case '-[WorklistTest testClassMock]' started.
Unknown.m:0: error: -[WorklistTest testClassMock] : *** -[NSProxy doesNotRecognizeSelector:sendSynchronousRequest:returningResponse:error:] called!
Test Case '-[WorklistTest testClassMock]' failed (0.000 seconds).

나는 이것에 대한 문서를 찾는 데 정말 어려움을 겪었지만, 수업 방법은 Ocmock이 지원하지 않는다고 가정합니다.

많은 인터넷 검색 후이 팁을 찾았습니다. 작동하지만 매우 번거 롭습니다.http://thom.org.uk/2009/05/09/mocking-class-methods-in-objective-c/

어쨌든 Ocmock 내에서 이것을 할 수 있습니까? 아니면 누군가 이런 종류의 일을 성취하기 위해 작성 될 수있는 영리한 Ocmock 카테고리 객체를 생각할 수 있습니까?

도움이 되었습니까?

해결책

루비의 세계에서 왔을 때, 나는 당신이 성취하려는 것을 정확히 이해합니다. 분명히, 당신은 말 그대로 3 시간 앞서 나보다 똑같은 일을하려고 노력했습니다 (시간대는? :-).

어쨌든, 나는 믿다 클래스 방법을 스터브하는 것은 문자 그대로 클래스에 도달해야하고 방법을 언제, 위치 또는 누가 호출하는지에 관계없이 메소드 구현을 변경해야하기 때문에 Ocmock에서 원하는 방식으로 지원되지 않습니다. 이것은 Ocmock이하는 것처럼 보이는 것과 대조적으로, 당신이 지정된 클래스의 "실제"객체 대신 직접 그리고 직접 조작하고 운영하는 프록시 객체를 제공하는 것과 대조적입니다.

예를 들어, nsurlconnection +sendsynchronousRequest : returningResponse : 오류 : 메소드를 스튜브에 포함시키는 것이 합리적입니다. 그러나 우리 코드 내 에서이 통화를 사용하는 것이 다소 묻혀있어서 그것을 매개 변수화하고 nsurlconnection 클래스의 모의 개체에서 교체하는 것이 매우 어색합니다.

이런 이유로, 나는 당신이 발견 한 "방법 스위 즈 링"접근 방식이 섹시하지는 않지만 클래스 방법을 스튜브에 맞추기 위해 정확히 무엇을하고 싶은지 생각합니다. 말하면 매우 번거로운 것은 극단적 인 것 같습니다. 우리는 그것이 "부적절하다"는 것에 동의하는 방법은 무엇입니까? 그럼에도 불구하고, 그것은 문제에 대한 매우 간결한 해결책입니다.

다른 팁

Ocmock 3에 대한 업데이트

Ocmock은 클래스 방법 스터브 지원을위한 구문을 현대화했습니다.

id classMock = OCMClassMock([SomeClass class]);
OCMStub(ClassMethod([classMock aMethod])).andReturn(aValue);

업데이트

Ocmock은 이제 상자 밖으로 스터브하는 클래스 메소드를 지원합니다. OP의 코드는 이제 게시 된대로 작동해야합니다. 클래스 메소드와 동일한 이름의 인스턴스 메소드가있는 경우 구문은 다음과 같습니다.

[[[[mock stub] classMethod] andReturn:aValue] aMethod]

보다 Ocmock의 기능.

원래 답변

배리 워크의 답변에 따른 샘플 코드.

가짜 클래스, 단지 연결을 스튜브하는 것만으로도 : Quequest : Delegate :

@interface FakeNSURLConnection : NSURLConnection
+ (id)sharedInstance;
+ (void)setSharedInstance:(id)sharedInstance;
+ (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id<NSURLConnectionDelegate>)delegate;
- (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id<NSURLConnectionDelegate>)delegate;
@end
@implementation FakeNSURLConnection
static id _sharedInstance;
+ (id)sharedInstance { if (!_sharedInstance) { _sharedInstance = [self init]; } return _sharedInstance; }
+ (void)setSharedInstance:(id)sharedInstance { _sharedInstance = sharedInstance; }
+ (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id<NSURLConnectionDelegate>)delegate {
    return [FakeNSURLConnection.sharedInstance connectionWithRequest:request delegate:delegate];
}
- (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id<NSURLConnectionDelegate>)delegate { return nil; }
@end

모의로 전환 :

{
    ...
    // Create the mock and swap it in
    id nsurlConnectionMock = [OCMockObject niceMockForClass:FakeNSURLConnection.class];
    [FakeNSURLConnection setSharedInstance:nsurlConnectionMock];
    Method urlOriginalMethod = class_getClassMethod(NSURLConnection.class, @selector(connectionWithRequest:delegate:));
    Method urlNewMethod = class_getClassMethod(FakeNSURLConnection.class, @selector(connectionWithRequest:delegate:));
    method_exchangeImplementations(urlOriginalMethod, urlNewMethod);

    [[nsurlConnectionMock expect] connectionWithRequest:OCMOCK_ANY delegate:OCMOCK_ANY];

    ...
    // Make the call which will do the connectionWithRequest:delegate call
    ...

    // Verify
    [nsurlConnectionMock verify];

    // Unmock
    method_exchangeImplementations(urlNewMethod, urlOriginalMethod);
}

다음은 클래스 방법을위한 스위스 구현이 포함 된 멋진 'Gist'입니다. https://gist.github.com/314009

테스트중인 메소드를 수정하여 클래스를 주입하는 매개 변수를 가져옵니다. NSURLConnection, 그런 다음 주어진 선택기에 응답하는 모의를 상대적으로 쉽게 통과하기가 쉽습니다 (선택기를 인스턴스 메소드로, 해당 클래스를 조롱하는 테스트 모듈에서 더미 클래스를 만들어야 할 수도 있습니다). 이 주입이 없으면 클래스 방법을 사용하고 있는데, 본질적으로 사용하고 있습니다. NSURLConnection (클래스) 싱글 톤으로서 싱글 톤 객체를 사용하는 반란에 빠졌고 코드의 테스트 가능성이 어려워졌습니다.

질문에 블로그 포스트에 대한 링크와 REFUX GIST는 아이디어를 블록 활성화 한 구현을 제시하게되었습니다. https://gist.github.com/1038034

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top