0

テスト駆動の iOS 開発の例に従っています。あるケースでは、デリゲートがエラー メソッドの「ダムダウン」バージョンを取得することを保証する単体テストがあります。したがって、あまり詳細には触れずに、関連するオブジェクトを以下に示します。

  • communicator:ネットワーク呼び出しを行うオブジェクト
  • manager:コミュニケーターに呼び出しを行うように指示し、結果をそのデリゲートにプッシュします。
  • デリゲート:StackOverflowManagerDelegateプロトコルに準拠するマネージャー デリゲート。結果を取得して処理します。

これがテストの内容です:

@implementation QuestionCreationTests

{
    @private
    StackOverflowManager *mgr;
}
- (void)testErrorReturnedToDelegateIsNotErrorNotifiedByCommunicator {
    MockStackOverflowManagerDelegate *delegate =
    [[MockStackOverflowManagerDelegate alloc] init];
    mgr.delegate = delegate;
    NSError *underlyingError = [NSError errorWithDomain: @"Test domain"
                                                   code: 0 userInfo: nil];
    [mgr searchingForQuestionsFailedWithError: underlyingError];
    XCTAssertFalse(underlyingError == [delegate fetchError],
                  @"Error should be at the correct level of abstraction");
}

これは、searchingForQuestionsFailedWithErrorStackOverflowManager での実装であり、マネージャーはコミュニケーターから返された元のエラーを単にダムダウンし、ダムダウンされたバージョンをデリゲートに送信します。

- (void)searchingForQuestionsFailedWithError:(NSError *)error {
    NSDictionary *errorInfo = [NSDictionary dictionaryWithObject: error
                                                          forKey: NSUnderlyingErrorKey];
    NSError *reportableError = [NSError
                                errorWithDomain: StackOverflowManagerSearchFailedError
                                code: StackOverflowManagerErrorQuestionSearchCode
                                userInfo:errorInfo];
    [delegate fetchingQuestionsOnTopic: nil
                       failedWithError: reportableError];
}

著者は、これが機能するためには、次のようにマネージャー デリゲート用のモック オブジェクトを実際に作成する必要があることを示唆しています。

@interface MockStackOverflowManagerDelegate : NSObject <StackOverflowManagerDelegate>
@property (strong) NSError *fetchError;

@end

@implementation MockStackOverflowManagerDelegate

@synthesize fetchError;

- (void)fetchingQuestionsOnTopic: (Topic *)topic
                 failedWithError: (NSError *)error {
    self.fetchError = error;
}

@end

これは の宣言ですStackOverflowManagerDelegate:

@protocol StackOverflowManagerDelegate <NSObject>    
- (void)fetchingQuestionsOnTopic: (Topic *)topic
                 failedWithError: (NSError *)error {    
@end

質問:私は本のすべての例に目を通し、著者が行っているような手動で作成したものの代わりに OCMock を使用しようとしています.. (私はそれがはるかに時間がかからないだろうと思っただけです)。これまでのところすべてが機能しています..しかし、私はここで立ち往生しています..fetchErrorデリゲートで呼び出されたプロパティを偽造するにはどうすればよいですか? これは私が今持っているものです:

- (void)testErrorReturnedToDelegateIsNotErrorNotifiedByCommunicator {
    id <StackOverflowManagerDelegate> delegate = 
       [OCMockObject mockForProtocol:@protocol(StackOverflowManagerDelegate)];
    mgr.delegate = delegate;

    NSError *underlyingError = [NSError errorWithDomain: @"Test domain"
                                                   code: 0 userInfo: nil];

    [mgr searchingForQuestionsFailedWithError: underlyingError];

    // compiler error here: no known instance method for selector 'fetchError'
    XCTAssertFalse(underlyingError == [mgr.delegate fetchError], @"error ");
}

マネージャーの根性では、マネージャーはデリゲートを呼び出します.. whereを使用してfetchingQuestionsOnTopic、そのメソッドを偽造できることを知っています..私は、 : I don'の結果をどうするかわかりませんデリゲートのモックアウトされたプロパティに格納する方法がわかりません。 [[[delegate stub] andCall:@selector(differentMethod:) onObject:differentObject] fetchingQuestionsOnTopic:[OCMArg any]]differentMethoddifferentMethod


更新:以下の回答のフォローアップとして..これは、基になるエラーが引き続きデリゲートで利用可能であることを保証する単体テストの実装です:

- (void)testErrorReturnedToDelegateDocumentsUnderlyingError {
    MockStackOverflowManagerDelegate *delegate =
    [[MockStackOverflowManagerDelegate alloc] init];
    mgr.delegate = delegate;
    NSError *underlyingError = [NSError errorWithDomain: @"Test domain"
                                                   code: 0 userInfo: nil];
    [mgr searchingForQuestionsFailedWithError: underlyingError];
    XCTAssertEqual([[[delegate fetchError] userInfo]
                          objectForKey: NSUnderlyingErrorKey], underlyingError,
                         @"The underlying error should be available to client code");
}

これがOCMockバージョンです。

- (void)testErrorReturnedToDelegateDocumentsUnderlyingErrorOCMock {
    id delegate =
    [OCMockObject mockForProtocol:@protocol(StackOverflowManagerDelegate)];
    mgr.delegate = delegate;

    NSError *underlyingError = [NSError errorWithDomain: @"Test domain"
                                                   code: 0 userInfo: nil];

    [[delegate expect] fetchingQuestionsFailedWithError:
       [OCMArg checkWithBlock:^BOOL(id param) {

        return ([[param userInfo] objectForKey:NSUnderlyingErrorKey] == underlyingError);

    }]];

    [mgr searchingForQuestionsFailedWithError: underlyingError];

    [delegate verify];
}
4

1 に答える 1

1

これを試して:

- (void)testErrorReturnedToDelegateIsNotErrorNotifiedByCommunicator {
    id delegate = 
       [OCMockObject mockForProtocol:@protocol(StackOverflowManagerDelegate)];
    mgr.delegate = delegate;

    NSError *underlyingError = [NSError errorWithDomain: @"Test domain"
                                                   code: 0 userInfo: nil];

    [[delegate expect] fetchingQuestionsOnTopic:OCMOCK_ANY 
                                failedWithError:[OCMArg isNotEqual:underlyingError]];

    [mgr searchingForQuestionsFailedWithError:underlyingError];

    [delegate verify];
}

マネージャーによって報告されたエラーのドメイン、コード、および userInfo をテストするには (よく覚えていれば、その本の別のテスト ケースです。ずっと前に読んだことがあります)、次のようにすることができます。

    id <StackOverflowManagerDelegate> delegate = 
       [OCMockObject mockForProtocol:@protocol(StackOverflowManagerDelegate)];
    mgr.delegate = delegate;

    NSError *underlyingError = [NSError errorWithDomain: @"Test domain"
                                                   code: 0 userInfo: nil];

    NSError *expectedError = [NSError errorWithDomain:@"expected domain" 
                                                 code:0/* expected code here*/ 
                                             userInfo:@{NSUnderlyingErrorKey: underlyingError}];
    [[delegate expect] fetchingQuestionsOnTopic:OCMOCK_ANY 
                                failedWithError:expectedError];

    [mgr searchingForQuestionsFailedWithError: underlyingError];

    [delegate verify];
于 2013-10-06T20:40:54.717 に答える