我正在尝试建立一种模式,通过创建类的“假”版本来模拟我不拥有的对象的类方法,然后调动原始版本以调用“假”版本的类方法并拥有假类在本身被模拟的共享对象上调用实例方法。
例如:
@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
发生的情况是我的启用模拟交换了 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 做的事情?我使用的这种模式似乎很有帮助——我不想认为这是一个死胡同。