【问题标题】:How to fail JUnit test from another thread如何使来自另一个线程的 JUnit 测试失败
【发布时间】:2022-06-28 23:04:00
【问题描述】:
考虑以下测试代码:
@Test
public void test() throws InterruptedException {
var latch = new CountDownLatch(1);
Executors.newSingleThreadExecutor().execute(() -> {
latch.countDown();
Assert.fail("Doesn't fail the test");
});
latch.await();
}
打印异常,但通过了。
线程“pool-1-thread-1”java.lang.AssertionError 中的异常:
没有通过测试
org.junit.Assert.fail(Assert.java:89) 在
MyTest.lambda$test$0(MyTest.java:55) 在
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) 在
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) 在
java.base/java.lang.Thread.run(Thread.java:834)
我尝试设置自定义未捕获异常处理程序setUncaughtExceptionHandler((t, e) -> Assert.fail(e.getMessage())),但这没有帮助。
【问题讨论】:
-
您能澄清一下您通过这种方式运行测试要达到的目的吗?我认为this answer 可能会有所帮助,尽管我不完全了解您想要达到的结果。
标签:
java
multithreading
junit
【解决方案1】:
您可以使用两个线程都可以访问的外部状态来执行此操作。请注意latch.countDown();应该在更改状态后添加
private volatile boolean failed = false;
@Test
public void test() throws InterruptedException {
var latch = new CountDownLatch(1);
Executors.newSingleThreadExecutor().execute(() -> {
failed = true;//or false depending on the use case
latch.countDown();
});
latch.await();
if(failed){
Assert.fail("Doesn't fail the test");
}
}
【解决方案2】:
您还可以使用 shutdown + awaitTermination 来确保所有任务都已完成,并使用 try-catch 和 AtomicBoolean 来断言没有“内部”引发 AssertionErrors。
AtomicBoolean failed = new AtomicBoolean(false);
ExecutorService executorService = Executors.newFixedThreadPool(PARALLEL_POOL_SIZE);
// start tasks.. maybe in a loop to generate load..
executorService.execute(() -> {
try {
// Test something
// ..
// Validate
assertThat(actual, equalTo(EXPECTED));
} catch (AssertionError e) {
failed.set(true);
throw e;
}
});
executorService.shutdown();
boolean terminatedInTime = executorService.awaitTermination(5, TimeUnit.SECONDS);
assertTrue(terminatedInTime);
assertFalse(failed.get());