【问题标题】:block callback not being called from a unit test program in IOS未从 IOS 中的单元测试程序调用块回调
【发布时间】:2013-12-18 20:37:00
【问题描述】:

我有以下设置。我有一个名为“View”的对象,我想在其中对包含两个 dispatch_async 调用的方法进行单元测试。

查看.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() 方法中的断点在测试模式下运行时不会被命中,但在我刚刚运行应用程序时会被命中。关于为什么它在应用程序正常运行但在运行单元测试时不起作用的任何想法?

【问题讨论】:

  • 很难测试线程代码,你的单元测试需要运行runloop

标签: ios objective-c unit-testing


【解决方案1】:

如果您希望能够对异步代码进行单元测试,则需要将 dispatch_async 包装在一个可以模拟的类中。此类将具有例如:

- (void)executeInBackground:(void(^)())task;
- (void)executeInForeground:(void(^)())task;

然后,在您的测试期间,您可以模拟这个类。不要实际调用任务,而是在调用任务时收集它们,并在测试中手动执行它们(实际上不是异步调用):

- (void)executeNextBackgroundTask;
- (void)executeNextForegroundTask;

然后您可以显式测试每个执行顺序。

【讨论】:

    【解决方案2】:

    您面临的问题是测试继续进行,即使它们没有完成。解决方案是停止运行循环,直到异步测试完成。

    你可以使用这个非常简单的开源宏 WAIT_WHILE(<expression>, <time_limit>) 在这里找到 https://github.com/hfossli/AGAsyncTestHelper

    - (void)testAsyncBlockCallback
    {
        __block BOOL jobDone = NO;
    
        [Manager doSomeOperationOnDone:^(id data) {
            jobDone = YES; 
        }];
    
        WAIT_WHILE(!jobDone, 2.0);
    }
    

    【讨论】:

    • 你需要内存屏障,否则编译器可以将你的while循环优化为while (!NO) {...}。此外,等待两秒钟直到运行循环到期以检查标志也不是最佳的。
    • 2 秒是任意的。可以设置为分钟或小时,但每个异步测试都需要一个上限,以防回调不发生。使用构建系统时的重要细节。这只是上限。如果超过该限制,它将抛出 XCTFail()
    • “超时”问题是,当块中的语句被执行时,运行循环不一定会返回。只有在此运行循环和模式上安排并执行了一个事件时,运行循环才会返回。
    • 这给我留下了更多问题 :)如何为异步操作编写单元测试?
    • 啊。我在这里找到了你的一个答案stackoverflow.com/a/21778069/202451我会调查一下
    猜你喜欢
    • 2015-03-05
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 2017-05-09
    • 2013-03-14
    • 2018-01-20
    • 1970-01-01
    • 2017-03-19
    相关资源
    最近更新 更多