Objective C - 单元测试和模拟对象?

ary*_*axt 5 unit-testing mocking objective-c ocmock

- (BOOL)coolMethod:(NSString*)str
{
     //do some stuff
     Webservice *ws = [[WebService alloc] init];
     NSString *result = [ws startSynchronous:url];
     if ([result isEqual:@"Something"])
     {
         //More calculation
         return YES;
     }
     return NO;
}
Run Code Online (Sandbox Code Playgroud)

我正在使用OCUnit在下面的方法中,我如何模拟我的WebService对象,或者方法"startSynchronous"的结果能够编写一个独立的单元测试?

是否可以在其中注入一些代码来创建模拟Web服务或在startSynchronous调用上返回模拟数据?

ary*_*axt 4

一种方法是使用您想要的类别和重写方法,您甚至可以重写 init 方法以返回模拟对象:

@interface Webservice (Mock)
- (id)init;
@end

@implementation Webservice (Mock)
- (id)init
{
     //WebServiceMock is a subclass of WebService
     WebServiceMock *moc = [[WebServiceMock alloc] init];
     return (Webservice*)moc;
}
@end
Run Code Online (Sandbox Code Playgroud)

这样做的问题是,如果您想让对象在 1 个测试文件中的不同测试中返回不同的结果,则无法做到这一点。(每个测试页可以重写每个方法一次)

编辑:

这是我发布的一个老问题,我想我会更新我现在如何编写可测试代码并对其进行单元测试的答案:)

视图控制器代码

@implementation MyViewController
@synthesize webService;

- (void)viewDidLoad
{
   [super viewDidLoad];

   [self.webService sendSomeMessage:@"Some_Message"];
}

- (WebService *)webService
{
   if (!_webService)
      _webService = [[WebService alloc] init];

   return _webService;
}

@end
Run Code Online (Sandbox Code Playgroud)

测试代码

@implementation MyViewControllerTest

- (void)testCorrectMessageIsSentToServer
{
   MyViewController *vc = [[MyViewController alloc] init];
   vc.webService = [OCMock niceMockForClass:[WebService class]];

   [[(OCMockObject *)vc.webService expect] sendSomeMessage@"Some_Message"];
   [vc view]; /* triggers viewDidLoad */
   [[(OCMockObject *)vc.webService verify];
}

@end
Run Code Online (Sandbox Code Playgroud)