我认为这个问题需要更新的答案,因为这里的大多数答案都已经过时了。
首先,对OP的问题:
我认为,将“预期的例外”概念引入JUnit是一个不好的举动,因为它可以在任何地方引发,并且可以通过测试。如果您抛出(并断言)非常特定于域的异常,那么它会起作用,但是当我处理需要绝对完美的代码时,我只会抛出此类异常,-大多数APIS只会抛出诸如IllegalArgumentException
或的内置异常。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() {
AxisRange range = new AxisRange(0,100);
Runnable act = () -> range.setLowerBound(200);
assertThrows(IllegalArgumentException.class, act);
}
这些测试有些奇怪,因为“ act”步骤实际上并未执行任何操作,但是我认为含义仍然很清楚。
在Maven上还有一个很小的小库,叫做catch-exception,它使用模仿式语法来验证是否抛出了异常。看起来不错,但是我不喜欢动态代理。就是说,那里的语法是如此巧妙,它仍然很诱人:
List myList = new ArrayList();
catchException(myList).get(1);
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 {
Assume.assumeFalse(BootstrappingUtilities.isCircleCI());
URL url = DLLTestFixture.class.getResource("USERDLL.dll");
String path = url.toURI().getPath();
path = path.substring(0, path.lastIndexOf("/"));
NativeLibrary.addSearchPath("USERDLL", path);
Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class);
assertThat(dll).isNotNull();
}