可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is it possible to test for multiple exceptions in a single JUnit unit test? I know for a single exception one can use, for example
@Test(expected=IllegalStateException.class)
Now, if I want to test for another exception (say, NullPointerException), can this be done in the same annotation, a different annotation or do I need to write another unit test completely?
回答1:
You really want the test to do one thing, and to test for that. If you're not sure as to which exception is going to be thrown, that doesn't sound like a good test to me.
e.g. (in pseudo-code)
try {
badOperation();
/// looks like we succeeded. Not good! Fail the test
fail();
}
catch (ExpectedException e) {
// that's fine
}
catch (UnexpectedException e) {
// that's NOT fine. Fail the test
}
so if you want to test that your method throws 2 different exceptions (for 2 sets of inputs), then you'll need 2 tests.
回答2:
This is not possible with the annotation.
With JUnit 4.7 you can use the new ExpectedException
rule
public static class HasExpectedException {
@Interceptor
public ExpectedException thrown= new ExpectedException();
@Test
public void throwsNothing() {
}
@Test
public void throwsNullPointerException() {
thrown.expect(NullPointerException.class);
throw new NullPointerException();
}
@Test
public void throwsNullPointerExceptionWithMessage() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("happened?");
throw new NullPointerException("What happened?");
}
}
More see
- JUnit 4.7: Interceptors: expected exceptions
- Rules in JUnit 4.7
If updating to JUnit 4.7 is not possible for you, you have to write a bare unit test of the form
public test() {
try {
methodCall(); // should throw Exception
fail();
}
catch (Exception ex) {
assert((ex instanceof A) || (ex instanceof B) || ...etc...);
...
}
}
回答3:
Use catch-exception:
// test
public void testDo() {
// obj.do(1) must throw either A or B
catchException(obj).do(1);
assert caughtException() instanceof A
|| caughtException() instanceof B;
// obj.do(2) must throw A but not SubclassOfA
catchException(obj).do(2);
assert caughtException() instanceof A
&& !(caughtException() instanceof SubclassOfA);
}
回答4:
Although this is not possible with JUnit 4, it is possible if you switch to TestNG, which allows you to write
@Test(expectedExceptions = {IllegalArgumentException.class, NullPointerException.class})
回答5:
How would you expect to "expected"s to work? A method can only throw one exception.
You would have to write a different unit test for each way the method can fail. So if the method legitimately throw two exceptions then you need two tests set up to force the method of throwing each exception.
回答6:
Keep the tests as simple and short as possible. The intention of a JUnit-Test is to test only one simple functionality or one single way of failure.
Indeed, to be safe, you should create at least one test for every possible execution way.
Normally, this is not always possible because if you have a method that analyses a string, there are so many possible string combinations that you cannot cover everything.
Keep it short and simple.
You can have 30-40 testing methods for one single method easily... does it really matter?
Regards
回答7:
@Test(expected=Exception.class)
This will throw all possible exceptions.