我有以下设置。我有一个名为“View”的对象,我想在其中对包含两个dispatch_async调用的方法进行单元测试。
view.m
typedef void (^onTaskCompletion)(); //defining the block
-(void) viewdidLoad
{
onTaskCompletion block = ^{
// callback into the block };
[self test1:block];
}
-(void) test1:(onTaskCompletion) block
{
//do something
dispatch_async(queue, ^{
// dispatch async into serial queue & do something
dispatch_async(dispatch_get_main_queue){
// calling the block
block();
};
};
}
当我运行IOS APP时,会调用 - (void)viewdidLoad中的块。工作得很好。但我遇到的问题是:
测试中的:XCTestCase(.m fie)
@property (retain) View *view;
-(void) testMyCode
{
onTaskCompletion block = ^{
// Never gets called.
};
[view test1:block];
}
当我尝试对此方法test1()进行单元测试时,该块永远不会被调用。
注意:dispatch_get_main_queue()中test1()方法中的断点在测试模式下运行时永远不会被击中,但在我运行应用程序时会被击中。有关为什么它在应用程序正常运行时有效但在运行单元测试时没有的想法?
答案 0 :(得分:1)
您面临的问题是,即使测试未完成,测试也会继续进行。解决方案是停止runloop,直到完成异步测试。
您可以使用此处https://github.com/hfossli/AGAsyncTestHelper
中的这个简单的开源宏WAIT_WHILE(<expression>, <time_limit>)
- (void)testAsyncBlockCallback
{
__block BOOL jobDone = NO;
[Manager doSomeOperationOnDone:^(id data) {
jobDone = YES;
}];
WAIT_WHILE(!jobDone, 2.0);
}
答案 1 :(得分:0)
如果您希望能够对异步代码进行单元测试,则需要将dispatch_async包装在可以模拟的类中。这个课将有例如:
- (void)executeInBackground:(void(^)())task;
- (void)executeInForeground:(void(^)())task;
然后,在测试期间,您可以模拟此课程。而不是实际调用任务,在调用任务时收集任务,并在测试中手动执行它们(实际上不是异步调用):
- (void)executeNextBackgroundTask;
- (void)executeNextForegroundTask;
然后你可以明确地测试每个执行顺序。