如何以惯用方式使用JUnit4来测试某些代码是否会抛出异常?
虽然我当然可以这样做:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
boolean thrown = false;
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
thrown = true;
}
assertTrue(thrown);
}
Run Code Online (Sandbox Code Playgroud)
我记得有一个注释或一个Assert.xyz或者其他东西,对于这些类型的情况来说,远不如KUndgy 和JUnit的精神.
关于大学的Java问题,有这段代码:
class MyExc1 extends Exception {}
class MyExc2 extends Exception {}
class MyExc3 extends MyExc2 {}
public class C1 {
public static void main(String[] args) throws Exception {
try {
System.out.print(1);
q();
}
catch (Exception i) {
throw new MyExc2();
}
finally {
System.out.print(2);
throw new MyExc1();
}
}
static void q() throws Exception {
try {
throw new MyExc1();
}
catch (Exception y) {
}
finally {
System.out.print(3);
throw new Exception();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我被要求提供输出.我回答13Exception in thread main …
如何进行第3次测试以检查异常消息中是否存在cause1?我还列出了前两个有缺点的测试.首先是不检查消息,第二个需要很多样板代码.
public class CheckExceptionsWithMockitoTest {
@Test(expected = RuntimeException.class)
public void testExpectedException1() {
A a = new A();
a.doSomethingThatThrows();
}
@Test
public void testExpectedException2() {
A a = new A();
try {
a.doSomethingThatThrows();
fail("no exception thrown");
} catch (RuntimeException e) {
assertThat(e.getMessage(), org.hamcrest.Matchers.containsString("cause1"));
}
}
@Test
public void testExpectedException3() {
A a = new A();
A spyA = org.mockito.Mockito.spy(a);
// valid but doesnt work
// doThrow(new IllegalArgumentException()).when(spyA).doSomethingThatThrows();
// invalid but in the spirit of what i want
//chekThrow(RuntimeException.class,containsString("cause1")).when(spyA).doSomethingThatThrows();
}
}
Run Code Online (Sandbox Code Playgroud)
我在Mockito中找不到有效的东西,但有些东西看起来可能(在语法层面)和能力. …
考虑以下代码:
@Rule ExpectedException expected = ExpectedException.none();
@Mock private MyObject mockMyObject;
private Converter converter; // Object under test
@Before public void before() {
MockitoAnnotations.initMocks(this);
when(mockMyObject.doSomething1()).thenReturn(1);
when(mockMyObject.doSomething2()).thenReturn("2");
}
@After public void after() {
verifyNoMoreInteractions(mockMyObject); // Exception test fails here
}
@Test public void testConverter() {
assertThat(converter.convert(mockMyObject), notNullValue());
verify(mockMyObject).doSomething1();
verify(mockMyObject).doSomething2();
}
@Test public void testConverterException() {
when(mockMyObject.doSomething1()).thenThrow(MyException.class);
expected.expect(MyException.class);
converter.convert(mockMyObject);
verify(mockMyObject).doSomething1(); // Never gets called
}
Run Code Online (Sandbox Code Playgroud)
我想要做的是,在异常测试中,标记我期望 doSomething1() 将被调用。然而,在 converter.convert() 处抛出异常,这意味着永远不会调用 verify() 调用。因此 verifyNoMoreInteractions() 在 after() 中失败。
注意:这是一个非常通用的示例,用于隐藏我们的任何内部代码。
在第一次和第二次通话时抛出的方法:
public void foo() throws Exception
Run Code Online (Sandbox Code Playgroud)
测试:
@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();
}
Run Code Online (Sandbox Code Playgroud)
你能帮我找到更好的解决方案吗?使用Mockito获得更好的解决方案也是可以接受的.
我的意思是更好,如果我可以在我的测试中避免尝试/捕获甚至多次尝试/捕获.在其他语言或jAssert我认为即使在春天也有如下陈述:
assertThrows(method(..)) //PseudoCode
Run Code Online (Sandbox Code Playgroud)
我认为与Mockito或JUnit 4.x有类似的事情.
我知道
@Test(expected=Exception)
Run Code Online (Sandbox Code Playgroud)
但是,如果我期待一次投掷并且测试结束之后,这将是可接受的.