In my Android project I want to test, with the same @Test, a class which can throw several times the same exception with different messages. I want my test to pass for a given list of messages and to fail for others.
Making some research on Junit I tried to implement this using @Rule
, expectMessage()
and Hamcrest matcher.
My implementation is currently based on the "Custom matcher" described here.
@RunWith(AndroidJUnit4.class)
public class TestException extends ApplicationTestCase {
@Rule public ExpectedException thrown= ExpectedException.none();
public TestException(){
super(AplicatyApplication.class);
}
@Test
public void testException() throws Exception {
thrown.expect(IndexOutOfBoundsException.class);
thrown.expectMessage(new MatchesPattern("*"));
Dummy.exec(0);
// do more stuff here ...
Dummy.exec(1);
// ...
Dummy.exec(2);
// ...
Dummy.exec(3); // I want my test to fail here
// ...
}
class MatchesPattern extends TypeSafeMatcher<String> {
private String pattern;
public MatchesPattern(String pattern) {
this.pattern = pattern;
}
@Override
protected boolean matchesSafely(String item) {
return item.matches(pattern)
&&
item.startsWith("My message")
&& (
item.endsWith("1")
||
item.endsWith("2")
);
}
@Override
public void describeTo(Description description) {
description.appendText("matches pattern ").appendValue(pattern);
}
@Override
protected void describeMismatchSafely(String item, Description mismatchDescription) {
mismatchDescription.appendText("does not match");
}
}
static class Dummy {
static void exec(int i){
if(i == 0)
return;
if(i == 1)
throw new IndexOutOfBoundsException("My message1");
if(i == 2)
throw new IndexOutOfBoundsException("My message2");
if(i == 3)
throw new IndexOutOfBoundsException("My message3");
}
}
}
Running this test I can see that the matcher is called just once, executing Dummy.exec(1);
.
The matchesSafely(String item)
returns true
and the the test ends with the status Passed.
All this seems to be Okay, with my understanding of the @Rule. I was waiting an exception : I got it; I was waiting a given message : I got it.
I can not find a way to continue the execution of my test once the first exception has been thrown.
My questions are :
- Is it possible to use @Rule to check more than one exception thrown into one tested method, or do I have to use the typical try/catch testing the exception message in every catch block?.
- Is there another/more elegant way to test this type of concerns.