我正在关注Test driven iOS Development中的示例,并且在一个案例中,有一个单元测试可以确保委托获得错误方法的'dumbed down'版本。因此,这里没有涉及太多细节的相关对象:
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");
}
这是StackOverflowManager中searchingForQuestionsFailedWithError
的实现,其中管理器只是简化了通信器返回的原始错误,并将愚蠢的版本发送给代理。
- (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 ");
}
在经理的胆量中,经理在委托上调用fetchingQuestionsOnTopic
..我知道我可以通过using [[[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];
}
答案 0 :(得分: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];