5

我有一个非常简单的Check类,它有一个阻塞waitForCondition()方法。这个方法是阻塞的。我想为此方法创建一些单元测试。首先,该方法应在满足条件时返回。其次,方法应该在被中断时返回。

在内部,Check该类有一个ArrayBlockingQueue并调用它的take()方法,所以我的测试实际上是关于正确编码条件的逻辑(应该如此)。在应用程序中,Check类的数据由另一个线程通过InputData方法提供。该InputData方法对传入数据执行逻辑,并在满足条件时在 ArrayBlockingQueue 中放置一个虚拟对象。这应该会导致waitForCondition()返回。

所以我的第一个想法是我可以InputData通过模拟测试并检查在满足条件时是否将虚拟对象添加到队列中。这将需要更改类的设计,因为队列是私有数据成员(除非可以模拟私有数据)。当满足条件时,它不会直接添加到队列中,而是InputData必须调用可以模拟的东西。

但是,如果方法正常运行,则存在检查waitForCondition()方法本身的问题。InputData这真的很简单的代码:

try {
        myArrayBlockingQueue.take();
        return true;
    } catch (InterruptedException ex) {
        return false;
    }

所以我想知道它是否值得想象中的麻烦:一个使用 a 创建另一个线程的测试Check,调用它waitForCondition(),然后在完成后返回一些东西。也许,使用 Executor 服务。模糊部分是如何同步assertTrue(...). 我发现这篇关于异步测试的文章看起来可以解决问题。

问题总结:

  1. 我是否应该更改设计以测试其中的逻辑InputData(),如果是,如何?
  2. 我应该忽略waitForCondition()只要InputData()被测试的测试吗?
  3. 还是只做需要做的事情(有点复杂的单元测试)并waitForCondition()直接测试更好?
4

3 回答 3

3

如果您在 Check 类的构造函数中注入 ArrayBlockingQueue 的实例,那么您的测试可以在测试中间注入适当的值。

然后你可以在超时的情况下运行单元测试,如果它在 100 毫秒左右没有返回则失败。

于 2012-07-11T15:15:40.370 回答
1

谢谢你的好链接!我遇到了一些类似的问题,也许这个链接比我做的更好。(我也很想看看这个问题的其他答案 - 这是一个好问题)

如果您不介意更改(至少暂时)您的实际代码(是的,这不是通常的单元测试实践!)您可以做一些我称之为“错误注入”的事情。

在我的实现中,您创建了一个从属性(或地图)读取的类,以在特定的独特点“做一些有趣的事情”。例如,您的财产可能会说

myClass.myMethod.blockingQueueTake = interrupt:
myClass.myLongCalculation = throw: java.lang.ArithmeticException(Failed to converge)

在您的代码中,您添加测试行,例如在您的之前queue.take()添加

TestSimulator.doCommand("myClass.myMethod.blockingQueueTake");

优点是一切都在真实的代码中发生,而不是一些 Mock,它会变得非常毛茸茸。(在我的情况下,SW 较旧,不是为单元测试编写/设计的,因此制作 Mock 非常困难)缺点是您可能想在之后删除或注释掉代码。所以它真的不是一个持续集成类型的单元测试,它更像是一次非常严肃的现实调试。所以,我承认,它远非理想,但是,它确实为我找到了一堆错误!

于 2012-07-11T15:06:56.610 回答
0

您还可以使用“测试运行器”类在循环中运行断言。该循环将在 try/catch 中运行断言。异常处理程序将简单地尝试再次运行断言,直到超时到期。我最近写了一篇关于这种技术的博客文章。该示例是用 groovy 编写的,但这个概念应该很容易适应 Java。

http://www.greenmoonsoftware.com/2013/08/asynchronous-functional-testing/

于 2013-08-15T03:02:55.103 回答