Bas*_*ass 5 junit testng unit-testing hamcrest assertj
Currently, whenever I need to fail a test in response to an exception thrown in another thread, I write something like this:
package com.example;
import java.util.ArrayList;
import java.util.List;
import org.testng.annotations.Test;
import static java.util.Arrays.asList;
import static java.util.Collections.synchronizedList;
import static org.testng.Assert.fail;
public final class T {
@Test
public void testFailureFromLambda() throws Throwable {
final List<Throwable> errors = synchronizedList(new ArrayList<>());
asList("0", "1", "2").parallelStream().forEach(s -> {
try {
/*
* The actual code under test here.
*/
throw new Exception("Error " + s);
} catch (final Throwable t) {
errors.add(t);
}
});
if (!errors.isEmpty()) {
errors.forEach(Throwable::printStackTrace);
final Throwable firstError = errors.iterator().next();
fail(firstError.getMessage(), firstError);
}
}
}
Run Code Online (Sandbox Code Playgroud)
A synchronized list may be replaced with an AtomicReference<Throwable>, but in general the code remains pretty much the same.
Is there any standard (and less verbose) way of doing the same using any of test frameworks available in Java (TestNG, JUnit, Hamcrest, AssertJ, etc.)?
默认情况下,当测试方法抛出异常时,TestNG 会失败。errored我相信 JUnit 也会发生同样的情况,如果测试抛出意外异常,它会将测试标记为。
如果您要处理Streams,那么您需要将其包装在一个RuntimeException变体中,这样 Java 就不会抱怨。TestNG 会自动使测试失败。
这是一个示例:
@Test
public void testFailureFromLambdaRefactored() {
asList("0", "1", "2").parallelStream().forEach(s -> {
try {
/*
* The actual code under test here.
*/
if (s.equals("2")) {
throw new Exception("Error " + s);
}
} catch (final Throwable t) {
throw new RuntimeException(t);
}
});
}
Run Code Online (Sandbox Code Playgroud)
这是针对涉及 lambda 和流的场景。一般来说,如果您想了解从@Test方法派生的新线程中发生的异常,那么您需要使用ExecutorService.
这是一个示例:
@Test
public void testFailureInAnotherThread() throws InterruptedException, ExecutionException {
List<String> list = asList("0", "1", "2");
ExecutorService service = Executors.newFixedThreadPool(2);
List<Future<Void>> futures = service.invokeAll(Arrays.asList(new Worker(list)));
for (Future future : futures) {
future.get();
}
}
public static class Worker implements Callable<Void> {
private List<String> list;
public Worker(List<String> list) {
this.list = list;
}
@Override
public Void call() throws Exception {
for (String s : list) {
if (s.equals("2")) {
throw new Exception("Error " + s);
}
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)