在第一次和第二次通话时抛出的方法:
public void foo() throws Exception
试验:
@test
public void testFooThrowsAtFirstAndSecondTime(){
boolean thrown;
try {
foo();
} catch (Exception e) {
thrown = true;
}
assertTrue(thrown);
thrown = false;
try {
foo();
} catch (Exception e) {
thrown = true;
}
assertTrue(thrown);
foo();
}
你能帮我找到更好的解决方案吗? 使用Mockito获得更好的解决方案也是可以接受的。
我的意思是,如果我可以在测试中避免尝试/捕获甚至多次尝试/捕获。在其他语言或jAssert中,我认为即使在春天也有如下声明:
assertThrows(method(..)) //PseudoCode
我认为与Mockito或JUnit 4.x有类似的事情。
我知道
@Test(expected=Exception)
但是,如果我期待一次投掷并且测试结束后,这只能被接受。
答案 0 :(得分:5)
我不认为每个方法调用都是可行的。
我会像这样编写测试:
@Test
public void testFooThrowsAtFirstAndSecondTime() throws Exception {
try {
foo();
fail("foo did not throw an exception");
} catch (Exception ex) { }
try{
foo();
fail("foo did not throw an exception");
} catch (Exception ex) { }
foo();
}
答案 1 :(得分:3)
如果你想在异常后恢复执行,那么这里的关键是the try block is crucial。您可以将其分解为方法或库,但必须在测试方法中调用它。
有效的方法:
我更喜欢的you and nrainier cite fail()
成功的try {
foo();
fail("foo did not throw an exception");
} catch (Exception ex) { }
成语:
List myList = new ArrayList();
catchException(myList).get(1); // myList is wrapped here
assert caughtException() instanceof IndexOutOfBoundsException;
catch-exception是一个库,与Mockito一样,包装传递的对象并在每个方法周围放置一个try块。 Mockito关于最终方法和类的警告也适用于此,所以这并不总是有效。
assertThrows(() -> methodThatThrows())
请注意,catch-exception处于“维护模式”,因为Java 8解决方案(下面)更加可靠。
任何解决方案,如assertThrows(new Runnable() {
@Override public void run() { methodThatThrows(); }
});
(Java 8)或:
public void assertThrows(Runnable block) {
try {
block.run();
fail("Block didn't throw.");
} catch (Exception ex) { }
}
...在Java 6/7中。重要的是, assertThrows在methodThatThrows 之前被调用,因此它可以调用methodThatThrows。感谢Stefan的pointing out Fishbowl,但你可以轻松自己写一个等价物:
@Test(expected=YourException.class)
不起作用的事情:
try
将上升到JUnit包装您的测试方法的ExpectedException
块。之后,Control永远不会返回测试方法。
JUnit4的assertThrows(methodCallThatThrows())
@Rule看起来很诱人,但因为它包装了整个测试方法,所以你必须在调用抛出异常的方法之前设置期望值。
任何看似methodCallThatThrows
的内容。在assertThrows
被调用之前,Java会尝试从try
中获取返回值,因此>中的任何{{1}}块都无法帮助。
答案 2 :(得分:1)
使用Java 8,您可以使用Fishbowl库。
@Test
public void testFooThrowsAtFirstAndSecondTime(){
Throwable firstException = exceptionThrownBy(() -> foo());
assertEquals(Exception.class, firstException.getClass());
Throwable secondException = exceptionThrownBy(() -> foo());
assertEquals(Exception.class, secondException.getClass());
foo()
}
也可以将此库与Java 6和7一起使用。但是你必须使用匿名类。
@Test
public void testFooThrowsAtFirstAndSecondTime(){
Throwable firstException = exceptionThrownBy(new Statement() {
public void evaluate() throws Throwable {
foo();
}
});
assertEquals(Exception.class, firstException.getClass());
Throwable secondException = exceptionThrownBy(new Statement() {
public void evaluate() throws Throwable {
foo();
}
});
assertEquals(Exception.class, secondException.getClass());
foo()
}
答案 3 :(得分:1)
如果你不幸的是必须为8之前的某个版本的java编写代码,那么你不能每个例外使用一行代码。
但是如果你使用的是java 8,那么就可以像Stefan Birkner所说的那样做。
现在,如果您不想仅为一个方法包含整个库,那么这里有一个适合您的方法,复制from my blog
public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
try
{
runnable.run();
}
catch( Throwable throwable )
{
if( throwable instanceof AssertionError && throwable.getCause() != null )
throwable = throwable.getCause();
assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
@SuppressWarnings( "unchecked" )
T result = (T)throwable;
return result;
}
assert false; //expected exception was not thrown.
return null; //to keep the compiler happy.
}
所以,你的测试代码就像这样:
@Test
public void testFooThrowsAtFirstAndSecondTime()
{
expectException( Exception.class, this::foo );
expectException( Exception.class, this::foo );
foo();
}
答案 4 :(得分:-1)
@Test(expected=Exception.class)