テスト駆動の 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");
}
これは、searchingForQuestionsFailedWithError
StackOverflowManager での実装であり、マネージャーはコミュニケーターから返された元のエラーを単にダムダウンし、ダムダウンされたバージョンをデリゲートに送信します。
- (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]]
differentMethod
differentMethod
更新:以下の回答のフォローアップとして..これは、基になるエラーが引き続きデリゲートで利用可能であることを保証する単体テストの実装です:
- (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];
}