【发布时间】:2013-12-08 12:34:40
【问题描述】:
我想为解析器编写单元测试,并想检查它是否正确地为列表中的所有输入字符串抛出异常。现在据我了解,JUnit 的标准方法是为每种情况编写单独的测试方法:
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
}
}
但由于我想对 20 或 50 个不同的字符串应用相同的测试,这似乎不切实际。
另一种方法是使用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.
}
}
}
}
但这很容易出错,我不会得到任何关于预期哪个异常的信息,如果抛出了不同的异常,它将被视为测试错误而不是失败。
我的解决方案是使用类似于下面expectException 的方法:
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;
}
}
在 JUnit 框架或相关库中是否有用于此目的的方法,或者您会建议一种不同的方法(或我拒绝的方法之一)来解决这个问题?
【问题讨论】:
-
你试过参数化JUnit测试吗?
-
@maheeka 这似乎是我想要的。你能写一个简短的例子并将其作为答案发布吗?
-
如果您觉得有用,请接受答案。 :)
-
JUnit 参数化测试是要走的路。您不需要多个线程或任何类似的东西。 JUnit4 可以为您处理。 (参考下面我的回答)