如何用模拟和预定义的答案替换异步调用?

时间:2013-06-01 17:42:14

标签: ios objective-c unit-testing ocunit ocmock

我有简单的类来执行网络内容。它是一个单例,它将NSOperationQueue封装在其中。当类'用户调用某种方法从网络获取数据时,此类创建从NSOperation继承的操作类的正确实例,并将其添加到队列以进行执行。显然,执行是在分离的线程中异步进行的。从网络NSOperation获取数据后,继承的对象会通知我的网络类,并通知感兴趣的代表有关数据已完成或错误的信息。

问题是,如何进行单元测试以检查网络类的逻辑?另外,我实际上并不想测试服务器端的行为。我只想用测试处理程序行为之后的模拟和预定义答案替换对服务器的实际异步调用。我想检查我的类是如何工作的,而不是服务器端。我通常理解用于测试这类东西的逻辑,但我对使用OCMock有点困惑。 最佳答案将是代码示例。我在我的项目中使用OCUnit和OCMock进行单元测试。

任何文章或github链接都将是完美的。

2 个答案:

答案 0 :(得分:3)

如果所有异步调用都通过类中的内部方法,则只需在对象上创建部分模拟并在该方法上使用stub / expect。然后,您可以正常调用公共方法,并使用模拟来验证是否调用了内部方法。使用部分模拟会停止调用实际实现,因此不应发生网络活动。

对于另一半,来自异步操作的回调,只需调用将直接从测试中调用的方法,然后通过使用OCUnit断言检查其状态来检查您的类是否做正确的事情,或者,如果它反过来使用回调,则使用另一个模拟。

答案 1 :(得分:1)

所以我知道这是关于OCMock的...但是我想我已经把它放在那里,我用Kiwi成功地完成了它,它看起来像这样。

it(@"should refresh the client's temporary API key if it is stale before sending the request", ^{
    ISLDataServiceAdd *addRequest = [ISLDataServiceAdd withRecord:@{ISLFieldContact_FirstName: @"Jason"} table:ISLTableContact];

    [[clientMock shouldEventually] receive:@selector(apiKey) andReturn:VALID_API_KEY];
    [[clientMock shouldEventually] receive:@selector(hasTemporaryAPIKey) andReturn:theValue(YES)];
    [[clientMock shouldEventually] receive:@selector(isTemporaryAPIKeyStale) andReturn:theValue(YES)];
    [[clientMock shouldEventually] receive:@selector(refreshTemporaryAPIKeyAndWait:)];

    [addRequest sendRequestUsingClient:clientMock completion:nil failure:nil];
});

sendRequestUsingClient:completion:failure:是一个异步调用,因此通过将shouldEventually与Kiwi一起使用,它知道在调用这些选择器之前需要等待一段时间(默认为1秒)。