使用 XCTestExpectation 单元测试异步函数,但它不会等待我设置的秒数 [英] unit test async function by using XCTestExpectation but it doesn't wait for the seconds I set

查看:97
本文介绍了使用 XCTestExpectation 单元测试异步函数,但它不会等待我设置的秒数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个继承 NSThreadMyService 类:

I have a MyService class which inherits NSThread:

标题:

@interface MyService : NSThread {
  -(void) startMe;
  -(void) doTask;
  ...
}

实现:

@implementation MyService
  -(void)startMe {
   [self start];
  }
  -(void) doTask {
    [self performSelector:@selector(checkData:) onThread:self withObject:nil waitUntilDone:YES];
  }

  -(void) checkData {
    ...
    // NOTE: dataChecked is an instance variable.
    dataChecked = YES;
  }
@end

我想对上面的 -(void)doTask 进行单元测试并验证 -(void)checkData 是否真的被调用了.我使用 OCMock 库 部分模拟 MyService.

I want to unit test the above -(void)doTask and verify that -(void)checkData is really called. I use OCMock library to partially mock MyService.

受到本教程(使用 XCTestExpectation) 的启发,我尝试了以下方法:

Inspired by this tutorial (use XCTestExpectation), I tried the following way:

       -(void) testCheckData {
          // partial mock MyService
          id myService = [OCMockObject partialMockForObject:[MyService getInstance]];
          [myService startMe];

          // function to test
          [myService doTask];

          // I setup expectation
          XCTestExpectation *expectation = [self expectationWithDescription:@"data checked"];

         // run assertion asynchronisely
         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            XCTAssertTrue([self isDataChecked]);
            // expectation fulfill
            [expectation fulfill];
        });

        // wait for 5 seconds
        [self waitForExpectationsWithTimeout:5.0 handler:^(NSError *error) {
            if (error) {
                NSLog(@"Timeout Error: %@", error);
            }
        }];
       }

但是,当我运行测试时,waitForExpectationsWithTimeout:handler: 不起作用,我的意思是它不会等待 5 秒,断言部分在被测函数被调用后立即运行.为什么它不等待 5 秒?

However, when I run my test, the waitForExpectationsWithTimeout:handler: doesn't work, I mean it doesn't wait for 5 seconds, the assertion part run immediately after function under test get called. Why it doesn't wait 5 seconds?

====== 更新 ======

我也试过不使用异步块:

I also tried not using async block :

-(void) testCheckData {
        // partial mock MyService
        id myService = [OCMockObject partialMockForObject:[MyService getInstance]];
        [myService startMe];

        // function to test
        [myService doTask];

        // I setup expectation
        XCTestExpectation *expectation = [self expectationWithDescription:@"data checked"];

       // run assertion
       XCTAssertTrue([self isDataChecked]);
       // expectation fulfill
       [expectation fulfill];

       // wait for 5 seconds
       [self waitForExpectationsWithTimeout:5.0 handler:^(NSError *error) {
          if (error) {
              NSLog(@"Timeout Error: %@", error);
          }
      }];
    }

但是还是出现同样的问题,没有等待5秒,测试立即返回,为什么?

But I still get the same problem, there is no waiting 5 seconds, the test return immediately, why?

===== AND ======

我可能会抱怨,如果我们忽略上面的更新 &返回查看我的原始代码使用异步块.我认为 waitForExpectations:5 应该执行我不需要使用 while 循环的等待,为什么我这么认为是因为教程.

I might be wroing, if we ignore my update above & back to see my original code using async block.I think waitForExpectations:5 should do the waiting that I don't need to use while loop, why I think this way is because of that tutorial.

如果我们检查那个教程,它首先显示使用while循环的旧风格等待,然后,它变成了不使用任何while循环的期望风格>,它所做的是设置期望->开始工作(在其工作的完成块中断言),它还有waitForExpectations:代码,它看起来和我的代码完全一样异步块.我想了解为什么我的原始代码看起来与教程相同但不起作用.我错过了什么吗?

If we check that tutorial, it firstly show the old stye of using while loop to wait, then, it changed to expectation style which doesn't use any while loop, what it does is set expectation->start work ( assert in the completion block of its work), it also has the waitForExpectations: code, which looks exactly the same as my code with the async block. I want to understand why my original code looks the same as the tutorial but doesn't work. Do I miss something?

推荐答案

好的,解决了.

我应该使用 dispatch_after 代替 dispatch_async,因为我的测试函数中没有完成块,而该教程中的示例有一个.所以,我需要改成这样:

I should use dispatch_after insteand of dispatch_async, because I don't have a completion block in my function under test while the example in that tutorial has one. So, I need to change to this:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        XCTAssert(...);
        [expectation fulfill];
});

如果你想使用 dispatch_async 请查看@Avi 的评论,在异步块中使用 while 循环等待.

If you want to use dispatch_async please check @Avi's comment, use a while loop in the async block to wait.

这篇关于使用 XCTestExpectation 单元测试异步函数,但它不会等待我设置的秒数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆