我认为这个问题需要一个更新的答案,因为这里的大多数答案都已经过时了。
首先是OP的问题:
我认为在 JUnit 中引入“预期异常”概念是一个糟糕的举动,因为该异常可以在任何地方引发,并且它会通过测试,所以我认为它已经被大家接受了。如果您抛出(并断言)非常特定于域的异常,它会起作用,但我只在处理需要绝对完美无瑕的代码时抛出这些类型的异常,--大多数 APIS 只会抛出内置异常,如 @ 987654322@ 或IllegalStateException。如果您进行的两个调用可能会引发这些异常,那么 @ExpectedException 注释会将您的测试标记为绿色,即使它是引发异常的错误行!
对于这种情况,我编写了一个类,我相信这里的许多其他人都已经编写了一个 assertThrows 方法:
public class Exceptions {
private Exceptions(){}
public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){
try{
actionThatShouldThrow.run();
fail("expected action to throw " + expectedException.getSimpleName() + " but it did not.");
}
catch(Exception e){
if ( ! expectedException.isInstance(e)) {
throw e;
}
}
}
}
如果抛出异常,此方法只会返回,允许您在测试中进行进一步的断言/验证。
使用 java 8 语法,您的测试看起来非常好。下面是使用该方法对我们的模型进行的更简单的测试之一:
@Test
public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() {
//setup
AxisRange range = new AxisRange(0,100);
//act
Runnable act = () -> range.setLowerBound(200);
//assert
assertThrows(IllegalArgumentException.class, act);
}
这些测试有点不靠谱,因为“act”步骤实际上并没有执行任何操作,但我认为意思还是很清楚的。
maven 上还有一个名为catch-exception 的小型库,它使用mockito 样式的语法来验证是否抛出了异常。它看起来很漂亮,但我不喜欢动态代理。也就是说,语法如此流畅,仍然很诱人:
// given: an empty list
List myList = new ArrayList();
// when: we try to get the first element of the list
// then: catch the exception if any is thrown
catchException(myList).get(1);
// then: we expect an IndexOutOfBoundsException
assert caughtException() instanceof IndexOutOfBoundsException;
最后,对于我进入这个线程时遇到的情况,如果满足某些条件,有一种方法可以忽略测试。
现在我正在努力通过名为 JNA 的 java native-library-loading-library 调用一些 DLL,但我们的构建服务器在 ubuntu 中。我喜欢尝试使用 JUnit 测试来推动这种开发——即使它们在这一点上还远非“单元”——。如果我在本地机器上,我想要做的是运行测试,但如果我们在 ubuntu 上,则忽略测试。 JUnit 4 对此有一个规定,称为Assume:
@Test
public void when_asking_JNA_to_load_a_dll() throws URISyntaxException {
//this line will cause the test to be branded as "ignored" when "isCircleCI"
//(the machine running ubuntu is running this test) is true.
Assume.assumeFalse(BootstrappingUtilities.isCircleCI());
//an ignored test will typically result in some qualifier being put on the results,
//but will also not typically prevent a green-ton most platforms.
//setup
URL url = DLLTestFixture.class.getResource("USERDLL.dll");
String path = url.toURI().getPath();
path = path.substring(0, path.lastIndexOf("/"));
//act
NativeLibrary.addSearchPath("USERDLL", path);
Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class);
//assert
assertThat(dll).isNotNull();
}