使用junit @Rule,expectCause()和hamcrest匹配器

Ale*_*ndr 24 java junit unit-testing maven

我有一个测试:

@Rule
public ExpectedException thrown = ExpectedException.none();
...
@Test
public void testMethod()
{
    final String error = "error message";
    Throwable expectedCause = new IllegalStateException(error);
    thrown.expectCause(org.hamcrest.Matchers.<Throwable>equalTo(expectedCause));
    someServiceThatTrowsException.foo();
}
Run Code Online (Sandbox Code Playgroud)

当通过mvn运行测试方法时,我收到错误:

java.lang.NoSuchMethodError:org.junit.rules.ExpectedException.expectCause(Lorg/hamcrest/Matcher;)V

测试编译好.

请帮帮我,无法理解如何测试异常的原因?

Har*_*ezz 23

试试这种方式:

@Rule public ExpectedException thrown = ExpectedException.none();

@Test public void testMethod() throws Throwable {
    final String error = "error message";
    Throwable expectedCause = new IllegalStateException(error);
    thrown.expectCause(IsEqual.equalTo(expectedCause));
    throw new RuntimeException(expectedCause);
}
Run Code Online (Sandbox Code Playgroud)

考虑不要通过equals检查原因,而是通过IsInstanceOf检查和/或在必要时将异常消息组合在一起.通过equals比较原因检查堆栈跟踪,这可能比您想要测试/检查的更多.像这样例如:

@Rule public ExpectedException thrown = ExpectedException.none();

@Test public void testMethod() throws Throwable {
    final String error = "error message";
    thrown.expectCause(IsInstanceOf.<Throwable>instanceOf(IllegalStateException.class));
    thrown.expectMessage(error);
    throw new RuntimeException(new IllegalStateException(error));
}
Run Code Online (Sandbox Code Playgroud)

  • 第二个例子是正确的方法。 (2认同)
  • 可以抛出Thrown.expectCause(IsInstanceOf.instanceOf(java.io.IOException.class));`是正确的,因为可以推断&lt;Throwable&gt; (2认同)

laz*_*lev 17

您可以使用此处所述的自定义匹配器(http://www.javacodegeeks.com/2014/03/junit-expectedexception-rule-beyond-basics.html)来测试异常的原因.

自定义匹配器

private static class CauseMatcher extends TypeSafeMatcher<Throwable> {

    private final Class<? extends Throwable> type;
    private final String expectedMessage;

    public CauseMatcher(Class<? extends Throwable> type, String expectedMessage) {
        this.type = type;
        this.expectedMessage = expectedMessage;
    }

    @Override
    protected boolean matchesSafely(Throwable item) {
        return item.getClass().isAssignableFrom(type)
                && item.getMessage().contains(expectedMessage);
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("expects type ")
                .appendValue(type)
                .appendText(" and a message ")
                .appendValue(expectedMessage);
    }
}
Run Code Online (Sandbox Code Playgroud)

测试用例

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void verifiesCauseTypeAndAMessage() {
    thrown.expect(RuntimeException.class);
    thrown.expectCause(new CauseMatcher(IllegalStateException.class, "Illegal state"));

    throw new RuntimeException("Runtime exception occurred",
            new IllegalStateException("Illegal state"));
}
Run Code Online (Sandbox Code Playgroud)


bor*_*jab 16

稍微简单介绍静态导入并检查类和原因异常的消息:

import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

@Test
public void testThatThrowsNiceExceptionWithCauseAndMessages(){

     expectedException.expect(RuntimeException.class );
     expectedException.expectMessage("Exception message");                                           
     expectedException.expectCause(allOf(instanceOf(IllegalStateException.class),
                                        hasProperty("message", is("Cause message"))) );

     throw new RuntimeException("Exception message", new IllegalStateException("Cause message"));
}
Run Code Online (Sandbox Code Playgroud)

您甚至可以使用hasProperty匹配器来断言嵌套原因或测试"getLocalizedMessage"方法.


卢声远*_* Lu 11

这是JUnit版本的问题.

ExpectedException.expectCause()4.11以来.

4.10或更低版本中没有这样的方法.

您应确保运行时JUnit版本> = 4.11,与编译版本相同.


Gmu*_*gra 6

总结一下.

使用JUnit 4(hamcrest 1.3,请注意,JUnit 4依赖于hamcrest-core,不包括org.hamcrest.beans包)

所以,你需要导入:

<dependency>
  <groupId>org.hamcrest</groupId>
  <artifactId>hamcrest-all</artifactId>
  <version>1.3</version>
  <scope>test</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud)

码:

import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void testThatThrowsNiceExceptionWithCauseAndMessages(){

  expectedException.expect(RuntimeException.class );
  expectedException.expectMessage("Exception message");                                           
  expectedException.expectCause(
    allOf(
      isA(IllegalStateException.class),
      hasProperty("message", is("Cause message"))
    )
  );

  throw 
    new RuntimeException("Exception message", 
      new IllegalStateException("Cause message"));
}
Run Code Online (Sandbox Code Playgroud)


wik*_*ier 5

通常我更喜欢以下结构:

expectedException.expectCause(isA(NullPointerException.class));

  • 最好添加该方法的来源:`import static org.hamcrest.CoreMatchers.isA;` (3认同)