在JUnit 5中,有更好的方法来断言方法是否抛出异常吗?
目前,我必须使用@Rule来验证我的测试是否抛出异常,但是这对于期望在我的测试中有多个方法抛出异常的情况不起作用。
在JUnit 5中,有更好的方法来断言方法是否抛出异常吗?
目前,我必须使用@Rule来验证我的测试是否抛出异常,但是这对于期望在我的测试中有多个方法抛出异常的情况不起作用。
assertThrows()
,它允许你在同一个测试中测试多个异常。在Java 8中支持lambda表达式的情况下,这是JUnit中测试异常的标准方式。import static org.junit.jupiter.api.Assertions.assertThrows;
@Test
void exceptionTesting() {
MyException thrown = assertThrows(
MyException.class,
() -> myObject.doThing(),
"Expected doThing() to throw, but it didn't"
);
assertTrue(thrown.getMessage().contains("Stuff"));
}
() ->
指向一个接受零个参数的lambda表达式。因此,预计抛出异常的"生产代码"位于所指向的代码块中(即花括号内的throw new...
语句)。 - Sam Brannenorg.junit.jupiter.api.Assertions.assertThrows
来断言异常。
public static < T extends Throwable > T assertThrows(Class< T > expectedType, Executable executable)
断言提供的可执行代码会抛出预期类型的异常,并返回该异常。
如果没有抛出异常或者抛出了不同类型的异常,此方法将失败。
如果您不想对异常实例执行其他检查,请简单地忽略返回值。
@Test
public void itShouldThrowNullPointerExceptionWhenBlahBlah() {
assertThrows(NullPointerException.class,
()->{
//do whatever you want to do here
//ex : objectName.thisMethodShoulThrowNullPointerExceptionForNullParameter(null);
});
}
Executable
在org.junit.jupiter.api
中。assertThrows(NoSuchElementException.class, myLinkedList::getFirst);
- fIwJlxSzApHEZIlobject -> object.methodCall()
可以被替换为 Object::methodCall
,但你不能用一个方法调用来替换 object -> object.getOneThing().getAnotherThing().doSomething()
。 - PixelMaster@Test
public void wrongInput() {
Throwable exception = assertThrows(InvalidArgumentException.class,
()->{objectName.yourMethod("WRONG");} );
}
assertThrowsExactly()
而不是assertThrows()
来匹配精确的异常类型。assertThrowsExactly(FileNotFoundException.class, () -> service.blah());
assertThrows()
,但是使用assertThrows
时,即使抛出的异常是子类型,你的断言也会通过。Class.isInstance(..)
来检查异常类型,Class.isInstance(..)
会返回true,即使抛出的异常是子类型。Throwable throwable = assertThrows(Throwable.class, () -> {
service.readFile("sampleFile.txt");
});
assertEquals(FileNotFoundException.class, throwable.getClass());
Junit5现在提供了一种断言异常的方式。
您可以测试常规异常和自定义异常。
一个常规异常场景:
ExpectGeneralException.java
public void validateParameters(Integer param ) {
if (param == null) {
throw new NullPointerException("Null parameters are not allowed");
}
}
ExpectGeneralExceptionTest.java
@Test
@DisplayName("Test assert NullPointerException")
void testGeneralException(TestInfo testInfo) {
final ExpectGeneralException generalEx = new ExpectGeneralException();
NullPointerException exception = assertThrows(NullPointerException.class, () -> {
generalEx.validateParameters(null);
});
assertEquals("Null parameters are not allowed", exception.getMessage());
}
您可以在此处找到用于测试CustomException的示例:断言异常代码示例
ExpectCustomException.java
public String constructErrorMessage(String... args) throws InvalidParameterCountException {
if(args.length!=3) {
throw new InvalidParameterCountException("Invalid parametercount: expected=3, passed="+args.length);
}else {
String message = "";
for(String arg: args) {
message += arg;
}
return message;
}
}
ExpectCustomExceptionTest.java
@Test
@DisplayName("Test assert exception")
void testCustomException(TestInfo testInfo) {
final ExpectCustomException expectEx = new ExpectCustomException();
InvalidParameterCountException exception = assertThrows(InvalidParameterCountException.class, () -> {
expectEx.constructErrorMessage("sample ","error");
});
assertEquals("Invalid parametercount: expected=3, passed=2", exception.getMessage());
}
assertThrows()
。我的示例来自文档http://junit.org/junit5/docs/current/user-guide/。import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
....
@Test
void exceptionTesting() {
Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
throw new IllegalArgumentException("a message");
});
assertEquals("a message", exception.getMessage());
}
我认为这是一个更简单的例子。
List<String> emptyList = new ArrayList<>();
Optional<String> opt2 = emptyList.stream().findFirst();
assertThrows(NoSuchElementException.class, () -> opt2.get());
在包含空 ArrayList
的可选项上调用 get()
将抛出 NoSuchElementException
。 assertThrows
声明了预期的异常并提供了一个 lambda 供应商(不带参数且返回一个值)。
感谢 @prime 的答案,我希望我对其进行了详细说明。
assertThrows
返回抛出的异常。因此,您可以像这样操作:NoSuchElementException e = assertThrows(NoSuchElementException.class, () -> opt2.get());
然后在下面,您可以对异常对象进行任何类型的断言。 - Captain Manimport static org.junit.jupiter.api.Assertions.assertThrows;
@Test
void exceptionTesting() {
assertThrows(MyException.class, myStackObject::doStackAction, "custom message if assertion fails...");
// note, no parenthesis on doStackAction ex ::pop NOT ::pop()
}
这是我在测试时确保已抛出异常的操作
//when
final var tripConsumer = new BusTripConsumer(inputStream);
final Executable executable = () -> tripConsumer.deserialiseTripData();
//then
assertThrows(IllegalArgumentException.class, executable);
我的解决方案:
protected <T extends Throwable> void assertExpectedException(ThrowingRunnable methodExpectedToFail, Class<T> expectedThrowableClass,
String expectedMessage) {
T exception = assertThrows(expectedThrowableClass, methodExpectedToFail);
assertEquals(expectedMessage, exception.getMessage());
}
您可以这样调用:
assertExpectedException(() -> {
carService.findById(id);
}, IllegalArgumentException.class, "invalid id");