有没有更好的方法来断言方法会在JUnit 5中引发异常?
当前,我必须使用@Rule来验证我的测试抛出异常,但这不适用于我期望多种方法在测试中抛出异常的情况。
有没有更好的方法来断言方法会在JUnit 5中引发异常?
当前,我必须使用@Rule来验证我的测试抛出异常,但这不适用于我期望多种方法在测试中抛出异常的情况。
Answers:
您可以使用assertThrows()
,它允许您在同一测试中测试多个异常。有了Java 8中对lambda的支持,这是在JUnit中测试异常的规范方法。
根据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...
大括号内的语句)。
在Java 8和JUnit 5(Jupiter)中,我们可以声明以下异常。使用org.junit.jupiter.api.Assertions.assertThrows
公共静态<T扩展Throwable> T assertThrows(Class <T> ExpectedType,可执行可执行文件)
断言所提供的可执行文件的执行将引发ExpectedType的异常并返回该异常。
如果没有引发异常,或者引发了其他类型的异常,则此方法将失败。
如果您不想对异常实例执行其他检查,则只需忽略返回值。
@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);
现在,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());
}
我认为这是一个更简单的例子
List<String> emptyList = new ArrayList<>();
Optional<String> opt2 = emptyList.stream().findFirst();
assertThrows(NoSuchElementException.class, () -> opt2.get());
调用get()
包含空值的可选内容ArrayList
将引发NoSuchElementException
。 assertThrows
声明预期的异常并提供一个lambda供应商(不带参数并返回值)。
感谢@prime的回答,我希望能详细阐述一下。
assertThrows
返回抛出的异常。因此,您可以像NoSuchElementException e = assertThrows(NoSuchElementException.class, () -> opt2.get());
下面所做的那样对所需的异常对象进行任何类型的断言。
您可以使用assertThrows()
。我的示例摘自docs 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());
}
一种更简单的衬垫。使用Java 8和JUnit 5的本示例不需要lambda表达式或花括号
import 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()
}
实际上,我认为该特定示例的文档中存在错误。预期的方法是ExpectThrows
public static void assertThrows(
public static <T extends Throwable> T expectThrows(