我有一个Java服务,现在将以批处理模式执行。多线程支持添加到服务中,因此对于每个批处理请求,线程池将专用于执行批处理。问题是我该如何测试?我有功能测试通过服务的线程版本,但不知何故,我觉得必须有一个习惯用于测试这个。
答案 0 :(得分:6)
真的没有“好”的方法来做到这一点。我可以建议的最好的事情是TestNG,它允许您注释您的测试方法并使它们同时在 n 线程中执行。例如:
@Test(invocationCount=10, threadPool=10)
public void testSomethingConcurrently() {
...
}
我的TestNG知识充其量是生锈的,但AFAIK应该同时调用testSomethingConcurrently
方法10次。对于代码运行多线程测试,这是一种很好的声明式方法。
你当然可以在JUnit中通过在循环中手动生成线程来做类似的事情,但这非常难看且难以使用。对于我正在进行的项目,我不得不这样做一次;那些测试是一个噩梦,因为他们的失败并不总是可重复的。
由于其不确定性,并发性测试很难并且容易受挫。这是为什么现在有这么大的推动使用更好的并发抽象的原因之一,这些抽象更容易“推理”并说服自己的正确性。
答案 1 :(得分:1)
通常,降低多线程应用程序的问题是时间问题。我怀疑能够在完整的多线程环境中执行单元测试需要对代码库进行大量更改才能实现。
但是,您可以做的是单独测试线程池的实现。
通过用测试代码替换线程的主体,您应该能够构建锁定和资源使用的病态条件。
然后,在单线程环境中对功能元素进行单元测试,您可以忽略时序。
虽然这并不完美,但它确保了可重复性,这对于您的单元测试非常重要。 (正如Daniel Spiewak的答案所暗示的那样)
答案 2 :(得分:1)
我用过
@Test(threadPoolSize = 100, invocationCount = 100)
@DataProvider(parallel = true)
并行执行100个线程100次。
答案 3 :(得分:0)
我同意Daniel,并发测试确实非常困难。
我没有并发测试的解决方案,但是当我想测试涉及多线程的代码时,我会告诉你我做了什么。 我的大部分测试都是使用JUnit和JMock完成的。由于JMock不适用于多个线程,因此我使用JMock的扩展来提供Executor和ScheduledExecutorService的同步版本。这些允许我测试目标是由单个线程中的多个线程运行的代码,在那里我也能够控制执行流程。正如我之前所说,这不会测试并发性。它只以单线程方式检查我的代码的行为,但它减少了我切换到多线程执行程序时得到的错误数量。
无论如何,我建议使用新的Java并发API。它使事情变得更加容易。