我阅读了其他针对此问题提出解决方案的帖子。但是,他们的解决方案需要将 hacky 代码添加到我的应用程序中才能对其进行测试。对我来说,干净的代码比单元测试更重要。
我经常在我的应用程序中使用 dispatch_async,但我在对其进行单元测试时遇到了问题。问题是 block 在我的测试完成后执行,因为它在主队列上异步运行。有没有办法以某种方式等到 block 被执行然后继续测试。
我不想仅仅因为单元测试而将完成传递给 block
- (viod)viewDidLoad
{
[super viewDidLoad];
// Test passes on this
[self.serviceClient fetchDataForUserId:self.userId];
// Test fails on this because it's asynchronous
dispatch_async(dispatch_get_main_queue(), ^{
[self.serviceClient fetchDataForUserId:self.userId];
});
}
- (void)testShouldFetchUserDataUsingCorrectId
{
static NSString *userId = @"sdfsdfsdfsdf";
self.viewController.userId = userId;
self.viewController.serviceClient = [[OCMockObject niceMockForClass:[ServiceClient class]];
[[(OCMockObject *)self.viewController.serviceClient expect] fetchDataForUserId:userId];
[self.viewController view];
[(OCMockObject *)self.viewController.serviceClient verify];
}
最佳答案
短暂运行主循环以让它调用异步 block :
- (void)testShouldFetchUserDataUsingCorrectId {
static NSString *userId = @"sdfsdfsdfsdf";
self.viewController.userId = userId;
self.viewController.serviceClient = [[OCMockObject niceMockForClass:[ServiceClient class]];
[[(OCMockObject *)self.viewController.serviceClient expect] fetchDataForUserId:userId];
[self.viewController view];
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
[(OCMockObject *)self.viewController.serviceClient verify];
}
我想这可能会在负载很重的系统上失败,或者如果主线程上有一堆其他东西(计时器或其他 block )。如果是这种情况,您需要运行运行循环更长的时间(这会减慢您的测试用例),或者重复运行它直到满足模拟对象的期望或达到超时(这需要向模拟对象添加一个方法来询问其期望是否已达到)。
关于objective-c - Objective-C - 单元测试 dispatch_async block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12463733/