Make sure that the method throws an exception when applying to any element of the list of values

I want to write unit tests for the parser and would like to check if it throws an exception correctly for all input lines in the 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 since I want to apply the same test to 20 or 50 different lines, this seems impractical.

An alternative would be to explicitly check for an exception with a catch :

 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 a mistake, and I do not get any information about which exception was expected, and if another exception was selected, it will be considered a test error, not an error.

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 this purpose in the JUnit framework or related library, or would you suggest a different approach (or one of my rejected approaches) to the problem?

+6
source share
3 answers

Use JUnit4 for test function with parameters. 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 information see http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/

+3
source

Use the fail() method:

 @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); fail("Parsing " + document + " should have thrown a ParseException"); } catch (ParseException e) { // Expected, do nothing. } } } 
+2
source

Here's an alternative, keeping the idea of fail from the previous answer if you care about getting the correct message in the exception.

 public final class ParseFailureTest { @Test public void testParseFailure() throws Exception { Map<String, String> documents = new LinkedHashMap<String,String>(); documents.put("[1 2]", "Missing comma"); documents.put("[1, 2,]", "Additional commas"); for (Entry<String,String> entry : documents.entrySet()) { try { Parser.parse(entry.getKey()); fail("Parsing " + entry.getKey() + " should have thrown a ParseException"); } catch (ParseException e) { assertEquals(entry.getValue(), e.getMessage()); } } } } 
0
source

All Articles