Check that a method throws an exception when applied to any element of a list of values
exception, java, junit
Solution
Use JUnit4 for Parameterized test feature. The following code should work.
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(value = Parameterized.class)
public class ParseTest {
private String parseValue;
public ParseTest(String parseValue) {
this.parseValue = parseValue;
}
@Parameters
public static Collection<Object[]> data() {
Object[][] data = new Object[][] { { "[1 2]" }, { "[1,2,]" } };
return Arrays.asList(data);
}
@Test(expected = ParseException.class)
public void testParseFailure1() throws Exception {
Parse.parse(parseValue);
}
}
For more info refer http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/
Problem
I want to write unit tests for a parser and would like to check that it correctly throws an exception for all input strings in a list. Now as I understand it, the standard approach with JUnit would be to write a separate test method for each case: ``` public final class ParseFailureTest1 { @Test(expected = ParseException.class) public void testParseFailure1() throws Exception { Parser.parse("[1 2]"); // Missing comma } @Test(expected = ParseException.class) public void testParseFailure2() throws Exception { Parser.parse("[1, 2,]"); // Additional commas } } ``` But as I want to apply the same test to 20 or 50 different strings, it seems impractical. An alternative would be to explicitly check for an exception with a `catch` block: ``` public final class ParseFailureTest2 { @Test public void testParseFailure() throws Exception { List<String> documents = Arrays.asList( "[1 2]", // Missing comma "[1, 2,]"); // Additional commas for (String document : documents) { try { Parser.parse(document); throw new AssertionError("Exception was not thrown"); } catch (ParseException e) { // Expected, do nothing. } } } } ``` But this is error prone and I won't get any information about which exception was expected and if a different exception was thrown, it would count as a test error and not a failure. My solution would be to use a method similar to `expectException` below: ``` public final class ParseFailureTest3 { @Test public void testParseFailure() throws Exception { List<String> documents = Arrays.asList( "[1 2]", // Missing comma "[1, 2,]"); // Additional commas for (final String document : documents) { expectException(ParseException.class, new TestRunnable() { @Override public void run() throws Throwable { Parser.parse(document); } }); } } public static void expectException(Class<? extends Throwable> expected, TestRunnable test) { try { test.run(); } catch (Throwable e) { if (e.getClass() == expected) { return; // Expected, do nothing. } else { throw new AssertionError(String.format("Wrong exception was thrown: %s instead of %s", e.getClass(), expected), e); } } throw new AssertionError(String.format("Expected exception was not thrown: %s", expected)); } public interface TestRunnable { void run() throws Throwable; } } ``` Is there a method for that purpose in the JUnit framework or a related library or would you suggest a different approach (or one of my rejected approaches) to the problem?