Использование junit @Rule, expectCause() и hamcrest matchers
У меня есть тест:
@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 метод проверки, я получаю ошибку:
java.lang.NoSuchMethodError: org.junit.rules.ExpectedException.expectCause(Lorg/Hamcrest/Сличитель;) В
Тестовый компилятор отлично.
Пожалуйста, помогите мне, не можете понять, как проверить причину исключения?
Ответы
Ответ 1
Вы можете использовать пользовательский матчи, как описано здесь (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"));
}
Ответ 2
Попробуйте так:
@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 и/или компилировать сообщение об исключении, если это необходимо. Сравнивая причину на равных, проверьте также стек, что может быть больше, чем вы хотели бы проверить/проверить. Например, например:
@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));
}
Ответ 3
Проблема с версией JUnit.
ExpectedException.expectCause()
с тех пор 4.11.
Нет такого метода в 4.10 или ниже.
Вы должны обеспечить свою версию JUnit версии >= 4.11, такую же, как ваша компиляционная версия.
Ответ 4
Немного короче со статическим импортом и проверкой как класса, так и сообщения об исключении причины:
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.
Ответ 5
Любой (класс <T> ) счётчик от hamcrest прекрасно работает:
@Rule
public ExpectedException thrown = ExpectedException.none();
...
@Test
public void testMethod()
{
thrown.expect(RuntimeException.class);
thrown.expectCause(org.hamcrest.Matchers.any(IllegalStateException.class));
}
Ответ 6
Подводя итог всем.
С JUnit 4 (hamcrest 1.3, и будьте осторожны, JUnit 4 зависит от ядра hamcrest, который не включает пакет org.hamcrest.beans)
Итак, вам нужно импортировать:
<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"));
}
Ответ 7
Обычно мне больше нравится следующая конструкция:
expectedException.expectCause(isA(NullPointerException.class));
Ответ 8
Импорт
<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();
}
Он также работает с подтипом причины. В других решениях я заметил, что они принимают супертип, это неправильно, по моему мнению.
Сообщение должно быть равно или содержать сообщение об ошибке причины.