等待我在JUnit测试用例中测试的代码生成的所有线程

时间:2010-08-18 14:24:58

标签: java multithreading unit-testing junit

如何在JUnit测试用例中确保被测试方法直接/间接生成的所有线程都是通过该作业完成的,这样我才能断言最终结果?

@Test
public void testMethod() {
 Result result=method();// may spawn multiple threads to set result.value

 Assert.assertTrue(result.getValue()==4); //should execute only after result.value is set to its final value.
}

3 个答案:

答案 0 :(得分:3)

真正的问题是,您如何在非测试代码中处理此案例? method()的API如何向其来电者保证何时会设置result.value

在编写测试时牢记这一点 - 目的是断言类及其方法在广告时表现。有时,弄清楚广告界面的内容可能是挑战的一半。

在这种情况下,我强烈建议您的Result对象的行为类似Future,因为其get()方法会阻塞,直到结果可用。 (或者,给它一个waitFor()方法或类似方法。)

如果您的方法没有提供任何特定的保证或阻止调用,那么您在测试中真正所做的就是每隔 x 秒检查一次值。循环,在测试上放置@Timeout以确保在“合理”时间内设置值。但这也是客户能够做到的,所以

  1. 这是一个非常有效的测试;
  2. 它强调该界面对客户端不是很有用,修改它会是一个好主意。

答案 1 :(得分:1)

我建议你在method()中的多个线程实例上调用Thread#join,按照这种方式,完成所有子线程。

答案 2 :(得分:0)

处理此问题的一种方法需要两个步骤:

  • 在等待工作线程时阻止主测试线程
  • 让每个工作线程在工作完成时发出主线程信号,在最后一个工作完成时解锁主线程。

理想情况下,如果所有工作人员都未在预期的时间范围内完成,您将希望主线程超时并且无法通过测试。使用ConcurrentUnit

非常简单
public class MyTest extends ConcurrentTestCase {
    @Test
    public void test() throws Throwable {
        int threads = 5;
        for (int i = 0; i < threads; i++) {
            new Thread(new Runnable() {
                public void run() {
                    threadAssertEquals(1, 1); // Perform assertions as needed
                    resume();
                }
            }).start();
        }

        threadWait(1000, threads); // Wait for 5 resume calls
    }
}