gpt4 book ai didi

ios - 如何模拟符合协议(protocol)并被 OCMock 模拟的对象的属性?

转载 作者:行者123 更新时间:2023-11-29 03:35:45 25 4
gpt4 key购买 nike

我正在按照 Test driven iOS Development 中的示例进行操作在一种情况下,有一个单元测试可确保委托(delegate)获得错误方法的“简化”版本。因此,这里无需过多介绍相关对象:

  • communicator:负责进行网络调用的对象
  • ma​​nager:指示 communicator 进行调用,然后将结果推送给它的 delegate。
  • delegate: 符合 StackOverflowManagerDelegate 协议(protocol)的管理器委托(delegate)。获取结果并对其进行处理。

所以这就是测试:

@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 的实现,其中管理器简单地简化了通信器返回的原始错误,并将简化后的版本发送给委托(delegate)。

- (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];
}

作者建议为了让这个工作..我们实际上必须像这样为经理委托(delegate)创建一个模拟对象:

@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 而不是像作者那样手动制作的示例。(我只是认为这将是一个耗时少很多)。到目前为止一切正常..但我被困在这里..如何在委托(delegate)上伪造一个名为 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 ");
}

在经理的内心深处,经理在委托(delegate)上调用了fetchingQuestionsOnTopic。我知道我可以通过using伪造那个方法。 [[[delegate stub] andCall:@selector(differentMethod:) onObject:differentObject] fetchingQuestionsOnTopic:[OCMArg any]] 其中 differentMethod 会做我想让它做的任何事情。 . 我只是不知道如何处理 differentMethod 的结果:我不知道如何将它存储在委托(delegate)的模拟属性中。


更新:作为下面答案的后续。这里是单元测试的实现,确保底层错误仍然对委托(delegate)可用:

- (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];
}

最佳答案

试试这个:

- (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];
}

要测试管理器报告的错误的域、代码和用户信息(如果我记得很好的话,这是那本书中的另一个测试用例 - 我很久以前读过),您可以执行以下操作:

    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];

关于ios - 如何模拟符合协议(protocol)并被 OCMock 模拟的对象的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19209725/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com