【问题标题】:Unit testing a method with delay in Objective-C在 Objective-C 中对具有延迟的方法进行单元测试
【发布时间】:2011-12-11 21:50:40
【问题描述】:

我想为一个延迟调用另一个方法的方法编写黑盒单元测试。有点像这样:

- (void) doSomething {
    // Do something
    [self performSelector:@selector(doSomethingLater) withObject:nil afterDelay:kDelay];
}

- (void) doSomethingLater { }

其中kDelay 是常量,doSomethingLater 是私有的。问题是kDelay 是 1 秒,我不想减慢单元测试的执行速度。

在黑盒方法下(或尽可能多地)对doSomething 进行单元测试的最佳方法是什么?

唯一想到的就是在类中添加一个方法来更改kDelay 的值,但这可能会被其他开发人员意外使用。有没有侵入性较小的替代方案?

【问题讨论】:

    标签: objective-c unit-testing black-box-testing


    【解决方案1】:

    我不知道它是否侵入性较小,但您可以使用您自己的不延迟版本来调整 -[NSObject performSelector:withObject:afterDelay:] 方法。

    Swizzling 意味着在运行时替换方法实现。查看免费的JRSwizzle library

    【讨论】:

    • 我想我会说它以不同的方式侵入。
    • 这种方法的问题在于,如果由于某种原因有人决定将 performSelector 更改为另一种延迟的方法,那么测试会变慢,没有人会知道原因。
    • 不过,如果能够混合常量就好了。
    • 您可以将常量更改为返回常量值的方法,然后调整该方法。
    【解决方案2】:

    我要查看的第一件事是检测该方法是否已执行。正如@Rob 所说,我会考虑以不同的方法进行调酒。可能是测试的一个本地设置了一个布尔值以表明它已被调用。

    下一个问题是减少延迟。由于 KDelay 是一个常数,因此您无法对它做任何事情。您可以将其更改为私有属性或您可以在测试和设置中访问的东西,但对于生产代码仍然是私有的。

    另一个选项(我还没有研究过它是否可能!)不是太担心检测正在执行的方法,而是看看你是否可以检测到调用是运行循环堆栈,等待被执行。如果您可以检测到挂起呼叫的存在而不是呼叫本身,那么您可以立即执行此操作,延迟变得无关紧要。

    【讨论】:

      【解决方案3】:

      您的测试是否要确保 doSomethingLater 已被调用并且它完成了它应该做的事情,而您想要做的只是缩短时间延迟?如果是这样,我建议您创建一个将常量值返回给 doSomething 的私有方法。比如:

      @implementation MyClass
      
      - (NSUInteger) getDelay {
          return kDelay;
      } 
      
      @end
      

      然后,您可以在运行时使用诸如 OCMock 其他测试框架之类的各种功能来存根 getDelay 的实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-20
        • 1970-01-01
        • 1970-01-01
        • 2018-04-28
        • 2014-01-08
        • 1970-01-01
        • 2019-09-16
        • 2010-09-07
        相关资源
        最近更新 更多