JUnit:有一种智能的方法来执行并行测试吗?

时间:2016-01-18 15:01:18

标签: java multithreading junit

在我的JUnit测试中,我想执行并行测试。

我的初稿不起作用:

@Test
public void parallelTestNotOk() {
    ExecutorService executor = Executors.newFixedThreadPool(10);
    Runnable testcaseNotOk = () -> fail("This failure is not raised.");
    IntStream.range(0, 20).forEach(i -> executor.submit(testcaseNotOk));
    executor.shutdown();
}

虽然每个testcaseNotOk都失败了,但这个测试用例会成功。为什么?因为fail未在主线程中调用,而是在并行调用?

我的第二稿有效,因为此测试用例按预期失败:

@Test
public void parallelTestOk() throws InterruptedException {
    ExecutorService executor = Executors.newFixedThreadPool(10);
    Callable<AssertionError> testcaseOk = () -> {
        try {
            fail("This failure will be raised.");
        } catch (AssertionError e) {
            return e;
        }
        return null;
    };
    List<Callable<AssertionError>> parallelTests = IntStream
            .range(0, 20).mapToObj(i -> testcaseOk)
            .collect(Collectors.toList());
    List<AssertionError> allThrownAssertionErrors = executor.invokeAll(parallelTests)
      .stream().map(future -> {
        try {
            return future.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }).filter(assertionError -> assertionError != null).collect(Collectors.toList());
    executor.shutdown();
    for (AssertionError e : allThrownAssertionErrors) {
        throw e;
    }
}

完成以下工作:

  1. testcaseOk中,要测试的代码嵌入到try / catch块中,每次AssertionError都会重新抛出。
  2. parallelTests包含20次testcaseOk
  3. ExecutorService执行所有parallelTests
  4. 如果AssertionError中出现testcaseOk,则会将其收集到allThrownAssertionErrors
  5. 如果allThrownAssertionErrors包含任何AssertionError,则会抛出它,并且测试用例parallelTestOk()将失败。否则就可以了。
  6. 我的parallelTestOk()似乎相当复杂。是否有更简单,更智能的方式(不使用TestNG)?

1 个答案:

答案 0 :(得分:2)

您的问题是您从不检查Future中的值以查看是否抛出了异常。

这将使测试正确失败:

@Test
public void parallelTestWillFail() throws InterruptedException, ExecutionException {
    ExecutorService executor = Executors.newFixedThreadPool(10);
    Runnable testcaseNotOk = () -> fail("This failure IS raised.");
    List<Future<?>> futures = IntStream.range(0, 20)
                                .mapToObj(i -> executor.submit(testcaseNotOk))
                                .collect(Collectors.toList());
    executor.shutdown();
    for(Future<?> f : futures){
        f.get();
    }
}