クラスの「偽の」バージョンを作成し、元のバージョンをスウィズして「偽の」バージョンのクラスメソッドを呼び出し、偽のクラスを作成することで、所有していないオブジェクトのクラスメソッドをモックするパターンを確立しようとしています。それ自体がモックされている共有オブジェクトでインスタンスメソッドを呼び出します。
例えば:
@interface FakeNSURLConnection : NSURLConnection
+ (void)enableMock:(id)mock;
+ (void)disableMock;
- (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id<NSURLConnectionDelegate>)delegate;
- (BOOL)canHandleRequest:(NSURLRequest *)request;
@end
@implementation FakeNSURLConnection
...
+ (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; }
+ (BOOL)canHandleRequest:(NSURLRequest *)request { return [FakeNSURLConnection.sharedInstance canHandleRequest:request]; }
- (BOOL)canHandleRequest:(NSURLRequest *)request { return NO; }
@end
何が起こるかというと、私のenableモックはNSURLConnectionとFakeNSURLConnectionのクラスメソッドを交換し、「sharedInstance」をFakeNSURLConnectionのモックにします。このように、モックが有効に[NSURLConnection canHandleRequest:request]
なると、のような呼び出しがモックメソッドに転送されます。
これはNSDateで少し注意が必要です。これは、フリーダイヤルのブリッジングを行う「抽象」クラスであるためだと思いますが、よくわかりません。オブジェクトを部分的にモックしたい場合は、Fakeクラスに実際の値を返すようにすることで、このモデルから最大のメリットを得ることができると思いました。したがって、次のようなものがあります。
@interface FakeNSDate : NSDate
...
- (id)date;
- (id)dateWithTimeInterval:(NSTimeInterval)seconds sinceDate:(NSDate *)date;
- (id)dateWithTimeIntervalSince1970:(NSTimeInterval)seconds;
- (id)dateWithTimeIntervalSinceNow:(NSTimeInterval)seconds;
- (id)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds;
- (id)distantFuture;
- (id)distantPast;
- (NSTimeInterval)timeIntervalSinceReferenceDate;
@end
@implementation FakeNSDate
...
+ (id)date { return [FakeNSDate.sharedInstance date]; }
- (id)date { return [[NSDate alloc] init]; }
...
@end
私はallocをスウィズリングしていないわけではありません。実際、NSDateのAPIにリストされているように、公開されているクラスメソッドをスウィズリングしているだけです。
私はこのコードを使用しています:
_baseDate = [NSDate dateWithTimeIntervalSinceNow:-1.0 * 90.0 * 60.0];
_nsDateMock = [OCMockObject partialMockForObject:[FakeNSDate sharedInstance]];
NSLog(@"_nsDateMock %@", [_nsDateMock class]);
[FakeNSDate enableMock:_nsDateMock];
[[[_nsDateMock stub] andReturn:_baseDate] date];
NSLog(@"DATE: %@", [NSDate date]);
このコードは正しく実行されますが(日付は1.5時間前であると報告されます)、次のエラーが表示されます。[NSProxy methodSignatureForSelector:] called!
問題は私がしていることですか、それともpartialMockForObjectがしていることですか?私が使用しているこのパターンは非常に役立つようです-行き止まりだとは思わないでしょう。