私にはテストがあります:
@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();
}
Mvn testメソッドを介して実行すると、エラーが発生します。
Java.lang.NoSuchMethodError:org.junit.rules.ExpectedException.expectCause(Lorg/hamcrest/Matcher;)V
テストは問題なくコンパイルされます。
助けてください、例外の原因をテストする方法がわかりませんか?
このようにしてみてください:
@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);
}
等しいのではなく、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));
}
ここで説明されているカスタムマッチャー( 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);
}
}
@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"));
}
静的インポートを使用し、クラスと原因例外のメッセージの両方をチェックして、もう少し簡単に説明します。
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"));
}
HasPropertyマッチャーを使用して、ネストされた原因をアサートしたり、「getLocalizedMessage」メソッドをテストしたりすることもできます。
すべてを要約します。
JUnit 4(hamcrest 1.3、注意してください、JUnit 4はorg.hamcrest.beansパッケージを含まないhamcrest-coreに依存しています)
したがって、インポートする必要があります:
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
コード:
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"));
}
Hamcrestのany(Class <T>)マッチャーはうまく機能します。
@Rule
public ExpectedException thrown = ExpectedException.none();
...
@Test
public void testMethod()
{
thrown.expect(RuntimeException.class);
thrown.expectCause(org.hamcrest.Matchers.any(IllegalStateException.class));
}
通常、私は以下の構造の方が好きです:
expectedException.expectCause(isA(NullPointerException.class));
組み込みマッチャーorg.hamcrest.Matchers.instanceOf
およびorg.junit.internal.matchers.ThrowableMessageMatcher.hasMessage
を使用して、これを完全に実行できます。
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.both;
import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage;
public class temp {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void youCannotDivideByZero() {
expectedException.expect(RuntimeException.class);
expectedException.expectMessage(equalTo("Division exception"));
expectedException.expectCause(both(hasMessage(equalTo("/ by zero"))).and(instanceOf(ArithmeticException.class)));
divide(1, 0);
}
private float divide(int first, int second) {
try {
return first / second;
} catch(ArithmeticException e) {
throw new RuntimeException("Division exception", e);
}
}
}
インポート
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>Java7-hamcrest-matchers</artifactId>
<version>1.3.0</version>
<scope>test</scope>
</dependency>
その後:
@Rule
public ExpectedException thrown = ExpectedException.none();
...
@Test
public void testMethod()
{
final String errorMessage = "error message";
Class<? extends Throwable> expectedCause = IllegalStateException.class;
thrown.expectCause(ExpectedException.exceptionWithMessage(expectedCause, errorMessage));
someServiceThatTrowsException.foo();
}
原因のサブタイプでも機能します。他の解決策では、彼らがスーパータイプを受け入れることを観察しましたが、それは私の意見では間違っています。
メッセージは等しいか、原因のエラーメッセージに含まれている必要があります。
Kotlin言語でメッセージとスローされた例外の原因を確認する例:
@get:Rule
val exceptionRule: ExpectedException = ExpectedException.none()
@Test
fun `test method`() {
exceptionRule.expect(NestedServletException::class.Java)
exceptionRule.expectMessage("error msg")
exceptionRule.expectCause(instanceOf(IllegalStateException::class.Java))
// ...