有没有更好的方法来断言方法在 JUnit 5 中引发异常?
目前,我必须使用@Rule 来验证我的测试是否引发了异常,但这不适用于我希望多个方法在我的测试中引发异常的情况。
您可以使用 assertThrows()
,它允许您在同一个测试中测试多个异常。在 Java 8 中支持 lambda,这是在 JUnit 中测试异常的规范方法。
根据 JUnit docs:
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"));
}
在 Java 8 和 JUnit 5 (Jupiter) 中,我们可以断言异常如下。使用 org.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);
});
}
该方法将使用 org.junit.jupiter.api
中的功能接口 Executable
。
参考 :
http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions
http://junit.org/junit5/docs/5.0.0-M2/api/org/junit/jupiter/api/Executable.html
http://junit.org/junit5/docs/5.0.0-M4/api/org/junit/jupiter/api/Assertions.html#assertThrows-java.lang.Class-org.junit.jupiter.api.function。可执行文件-
assertThrows(NoSuchElementException.class, myLinkedList::getFirst);
object -> object.methodCall()
可以替换为 Object::methodCall
,但您不能将 object -> object.getOneThing().getAnotherThing().doSomething()
替换为方法调用。
他们在 JUnit 5 中对其进行了更改(预期:InvalidArgumentException,实际:调用方法),代码如下所示:
@Test
public void wrongInput() {
Throwable exception = assertThrows(InvalidArgumentException.class,
()->{objectName.yourMethod("WRONG");} );
}
现在 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 的示例:assert exception code sample
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());
}
TL;DR:如果您使用的是 JUnit 5.8.0+ 版本,则可以使用 assertThrowsExactly()
而不是 assertThrows()
来匹配确切的异常类型。
assertThrowsExactly(FileNotFoundException.class, () -> service.blah());
您可以使用 assertThrows()
,但使用 assertThrows
,即使抛出的异常是子类型,您的断言也会通过。
这是因为,JUnit 5 通过调用 Class.isIntance(..)
检查异常类型,即使抛出的异常是子类型,Class.isInstance(..)
也会返回 true。
解决方法是在 Class 上断言:
Throwable throwable = assertThrows(Throwable.class, () -> {
service.readFile("sampleFile.txt");
});
assertEquals(FileNotFoundException.class, throwable.getClass());
您可以使用 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());
那样做,然后在下面你可以对你想要的异常对象做任何类型的断言。
一个更简单的班轮。此示例使用 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(
我的解决方案:
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");
这是一个简单的方法。
@Test
void exceptionTest() {
try{
model.someMethod("invalidInput");
fail("Exception Expected!");
}
catch(SpecificException e){
assertTrue(true);
}
catch(Exception e){
fail("wrong exception thrown");
}
}
只有当您期望的异常被抛出时,它才会成功。
不定期副业成功案例分享
() ->
指向 接受零参数的 lambda 表达式。因此,预期会引发异常的“生产代码”位于指向的代码块中(即大括号内的throw new...
语句)。