2008-10-21 67 views
7

我有一个Java服务,现在将以批处理模式执行。多线程支持被添加到服务中,所以对于每个批处理请求,线程池将专用于执行批处理。问题是我如何测试这个?我有服务的线程版本下传递的功能测试,但不知何故,我觉得必须有一个测试这个成语。如何为多线程支持添加测试?

回答

6

真的没有一个“好”的方法来做到这一点。我可以建议的最好的事情就是TestNG,它允许你注释你的测试方法并使它们同时在n线程中执行。例如:

@Test(invocationCount=10, threadPool=10) 
public void testSomethingConcurrently() { 
    ... 
} 

我TestNG的知识是生锈的最好的,但据我所知应该同时调用testSomethingConcurrently方法的10倍。这是针对您的代码运行多线程测试的一种很好的声明性方法。

您当然可以在JUnit中通过在循环中手动产生线程来做类似的事情,但这是非常难看和难以操作的。我曾经为我正在进行的一个项目做过一次这样的事情;这些测试是一个噩梦来处理,因为他们的失败并不总是可重复的。

由于其非确定性性质,并发测试很困难且容易受挫。这就是为什么现在有这么大的推动力来使用更好的并发抽象的原因之一,这些抽象更易于“推理”并说服自己的正确性。

0

我同意丹尼尔的并发测试的确很困难。

我没有并发测试的解决方案,但我会告诉你我想要测试涉及多线程的代码时要做什么。 我的大部分测试都是使用JUnit和JMock完成的。由于JMock不能很好地处理多个线程,因此我使用JMock的扩展来提供Executor和ScheduledExecutorService的同步版本。这些允许我测试旨在由单个线程中的多个线程运行的代码,其中我也能够控制执行流程。正如我之前所说的,这不会测试并发性。它仅以单线程方式检查我的代码的行为,但它减少了我切换到多线程执行程序时得到的错误数量。

无论如何,我建议使用新的Java并发API。它使事情变得更容易。

1

通常会导致多线程应用程序的问题是计时问题。我怀疑为了能够在完整的多线程环境中执行单元测试,需要对代码库进行大量更改才能做到这一点。

尽管如此,您可能能够做的是单独测试线程池的实现。

通过用测试代码替换线程正文,您应该能够构建您的锁定和资源使用的病态条件。

然后,单元测试单线程环境中的功能元素,您可以忽略时序。

虽然这并不完美,但它确保可重复性,这对您的单元测试非常重要。(如在丹尼尔Spiewak的回答提到)

1

我用

@Test(threadPoolSize = 100, invocationCount = 100) 
    @DataProvider(parallel = true) 

并列执行100次100个线程。