Got a question regarding the usage of junit's ExpectedException rule:
As suggested here: junit ExpectedException Rule starting from junit 4.7 one can test exceptions like this (which is much better then the @Test(expected=Exception.class)):
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void testFailuresOfClass() {
Foo foo = new Foo();
exception.expect(Exception.class);
foo.doStuff();
}
Now I needed to test several exceptions in one test method and got a green bar after running the following test and thus thought every test passed.
@Test
public void testFailuresOfClass() {
Foo foo = new Foo();
exception.expect(IndexOutOfBoundsException.class);
foo.doStuff();
//this is not tested anymore and if the first passes everything looks fine
exception.expect(NullPointerException.class);
foo.doStuff(null);
exception.expect(MyOwnException.class);
foo.doStuff(null,"");
exception.expect(DomainException.class);
foo.doOtherStuff();
}
However after a while I realized that the testmethod is quit after the first check passes. This is ambiguous to say the least. In junit 3 this was easily possible... So here is my question:
How can I test several exceptions within one test using an ExpectedException Rule?
Short answer: You can't.
If the first call - to foo.doStuff()
- throws an exception, you will never reach foo.doStuff(null)
. You'll have to split your test up into several (and for this trivial case I'd propose going back to the simple notation, without ExpectedException
):
private Foo foo;
@Before
public void setUp() {
foo = new Foo();
}
@Test(expected = IndexOutOfBoundsException.class)
public void noArgsShouldFail() {
foo.doStuff();
}
@Test(expected = NullPointerException.class)
public void nullArgShouldFail() {
foo.doStuff(null);
}
@Test(expected = MyOwnException.class)
public void nullAndEmptyStringShouldFail() {
foo.doStuff(null,"");
}
@Test(expected = DomainException.class)
public void doOtherStuffShouldFail() {
foo.doOtherStuff();
}
If you really want one and only one test, you can fail
if no error is thrown, and catch the things you expect:
@Test
public void testFailuresOfClass() {
Foo foo = new Foo();
try {
foo.doStuff();
fail("doStuff() should not have succeeded");
} catch (IndexOutOfBoundsException expected) {
// This is what we want.
}
try {
foo.doStuff(null);
fail("doStuff(null) should not have succeeded");
} catch (NullPointerException expected) {
// This is what we want.
}
// etc for other failure modes
}
This gets quite messy pretty fast, though, and if the first expectation fails, you won't see if anything else fails as well, which can be annoying when troubleshooting.