问题
So I've been unit testing an android application, and while there are cases that I test with fail scenarios, I don't test them quite the way this answer is suggesting (Try catch in a JUnit test).
I test it the way it shows on the code below. The answer is suggesting that you should have on test method signature the "throws Exception", since if it actually throws an exception you don't expect, it will fail the test. However i tried it with and without that piece of code, and it fails the same way. The answer provided above, also approaches this kind of test with the use of "rule", which i haven't used, since everything i need i have them inside my try catch block, and the instantiations are done inside a @Before method.
@Test
public void testMethod() {
try{
//code that will throw exception
fail("Exception was not thrown");
} catch (/* types of exceptions */) {
//my asserts
}
}
What I'm after is which approach is considered "best practice" and the reason behind it.
回答1:
There's the expected
attribute of the @Test
annotation to define test cases that check if specific exceptions get raised. Alternatively there's the @Rules
annotation for more specific control and a somewhat deprecated "try-catch" idiom. For samples see this and the junit wiki.
@Test(expected = IllegalArgumentException.class)
回答2:
Since this was tagged with JUnit4 my preferred is to use the expected attribute of the @Test annotation
@Test(expected = NullPointerException.class)
However, if you need to check further properties of the thrown exception, you can use ExpectedException, it's quite powerful:
@Rule
public ExpectedException exceptionRule = ExpectedException.none();
@Test
public void whenExceptionThrown_thenRuleIsApplied() {
exceptionRule.expect(NumberFormatException.class);
exceptionRule.expectMessage("For input string");
Integer.parseInt("1a");
}
I would suggest using JUnit 5 however, where you can make use of Java 8 constructs such as passing a Lambda for the check, which makes your code quite declarative and concise.
Good article for both JUnit 4 and JUnit 5: https://www.baeldung.com/junit-assert-exception
回答3:
Personally I use the assertThrows and assign the result to a Throwable so I can check the message. The reason for doing this is, for example, when I need to check validations which return IllegalArgument, I can check if the message is the expected one for the field is missing.
@Test
public void testSomething_shouldThrowException() {
String expectedMessage = "Exception running the method";
Throwable exception = Assertions.assertThrows(YourException.class, ()
-> {
bean.doSomething(dummyRequest);
});
Assert.assertEquals(expectedMessage, exception.getMessage());
}
来源:https://stackoverflow.com/questions/58337403/unit-test-best-practices-when-testing-exceptions