Mockito Как издеваться и утверждать выброшенное исключение?


Ответы:


75

Решение в стиле BDD (обновлено до Java 8)

Сам по себе Mockito - не лучшее решение для обработки исключений, используйте Mockito с Catch-Exception

Mockito + Catch-Exception + AssertJ

given(otherServiceMock.bar()).willThrow(new MyException());

when(() -> myService.foo());

then(caughtException()).isInstanceOf(MyException.class);

Образец кода

зависимости


2
Что такое «ловушка-исключение»? Есть ссылка?
Дункан Джонс

что caughtException?
Саиф Масаде,

Понял, это исходит отcom.googlecode.catchexception.CatchException.caughtException;
Саиф Масаде

212

Сначала отвечу на ваш второй вопрос. Если вы используете JUnit 4, вы можете аннотировать свой тест с помощью

@Test(expected=MyException.class)

чтобы утверждать, что произошло исключение. А чтобы "издеваться" над исключением с помощью mockito, используйте

when(myMock.doSomething()).thenThrow(new MyException());

2
этот подход неприемлем для случая, когда вы тестируете метод объекта, который имеет некоторое состояние. Например, есть метод объекта, который выдает исключение, если вы вызываете его во второй раз. И вам нужно протестировать, чтобы убедиться, что он вызывает исключение во время второго вызова метода, а не первого. Если он вызывает MyException во время первого вызова метода (на этапе подготовки), он должен пройти тест. Но при таком подходе мы не можем проверить, во время какого вызова метода возникает исключение.
Снег

Хотя в этом случае мы можем перехватить исключение из первого вызова метода и обернуть его в RuntimeException.
Снег

29

Если вы хотите проверить сообщение об исключении, вы можете использовать JUnit ExpectedException с Mockito:

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

@Test
public void testExceptionMessage() throws Exception {
    expectedException.expect(AnyException.class);
    expectedException.expectMessage("The expected message");

    given(foo.bar()).willThrow(new AnyException("The expected message"));
}

given()откуда это взялось?
Мохаммад Фейсал


Я также предпочитаю использовать @Rule, потому что таким образом я могу проверить ожидаемое сообщение или причину или другие вещи, относящиеся к исключению. Для проверки причины исключения я использую: expectedException.expectCause (Mockito.sameInstance (expectedException)) или expectedException.expectCause (Mockito.instanceOf (MyException.class)) и некоторые другие, которые пригодятся.
Crenguta S

19

Обновленный ответ от 19.06.2015 (если вы используете java 8)

Просто используйте assertj

Использование assertj-core-3.0.0 + Java 8 Lambdas

@Test
public void shouldThrowIllegalArgumentExceptionWhenPassingBadArg() {
assertThatThrownBy(() -> myService.sumTingWong("badArg"))
                                  .isInstanceOf(IllegalArgumentException.class);
}

Ссылка: http://blog.codeleak.pl/2015/04/junit-testing-exceptions-with-java-8.html


работал для меня ... Также мы можем проверить сообщение об исключении, а также .assertThatThrownBy (() -> myService.sumTingWong ("badArg")). hasMessage ("test") .isInstanceOf (IllegalArgumentException.class);
Sritam Jagadev

17

Если вы используете JUnit 4 и Mockito 1.10.x, аннотируйте свой метод тестирования с помощью:

@Test(expected = AnyException.class)

и выбросить желаемое использование исключения:

Mockito.doThrow(new AnyException()).when(obj).callAnyMethod();

16

Сделайте исключение таким:

when(obj.someMethod()).thenThrow(new AnException());

Убедитесь, что это произошло, либо заявив, что ваш тест выдаст такое исключение:

@Test(expected = AnException.class)

Или с помощью обычной имитационной проверки:

verify(obj).someMethod();

Последний вариант необходим, если ваш тест предназначен для доказательства того, что промежуточный код обрабатывает исключение (т.е. исключение не будет выброшено из вашего метода тестирования).


verifyУтверждает ли вызов исключение?
NilsH

@NilsH Нет. Но при условии, что whenпредложение верное, оно должно было вызвать исключение.
Дункан Джонс

10

Используйте doThrow от Mockito, а затем поймайте нужное исключение, чтобы утверждать, что оно было сгенерировано позже.

@Test
public void fooShouldThrowMyException() {
    // given
    val myClass = new MyClass();
    val arg = mock(MyArgument.class);
    doThrow(MyException.class).when(arg).argMethod(any());
    Exception exception = null;

    // when
    try {
        myClass.foo(arg);
    } catch (MyException t) {
        exception = t;
    }

    // then
    assertNotNull(exception);
}

5

Используя mockito, вы можете сделать исключение.

when(testingClassObj.testSomeMethod).thenThrow(new CustomException());

Используя Junit5, вы можете утверждать исключение, проверять, выбрасывается ли это исключение при вызове метода тестирования .

@Test
@DisplayName("Test assert exception")
void testCustomException(TestInfo testInfo) {
    final ExpectCustomException expectEx = new ExpectCustomException();

     InvalidParameterCountException exception = assertThrows(InvalidParameterCountException.class, () -> {
            expectEx.constructErrorMessage("sample ","error");
        });
    assertEquals("Invalid parametercount: expected=3, passed=2", exception.getMessage());
}

Пример можно найти здесь: assert exception junit


Спасибо ! Работал для меня
HariKishore

1

Вне зависимости от mockito, исключение можно поймать и подтвердить его свойства. Чтобы убедиться, что исключение действительно произошло, установите ложное условие в блоке try после оператора, который вызывает исключение.


Ответ @MariuszS правильно отвечает на то, что вы говорите, не имеет отношения к Mockito
pringi

@pringi Спасибо, я вижу, что вопрос касался как издевательства над исключением, так и его перехвата. Мне интересно, зависит ли это от какого-либо поведения тестируемого кода.
eel ghEEz

1

Или если ваше исключение выброшено из конструктора класса:

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

@Test
public void myTest() {    

    exception.expect(MyException.class);
    CustomClass myClass= mock(CustomClass.class);
    doThrow(new MyException("constructor failed")).when(myClass);  

}

-1

Утверждение по сообщению об исключении:

    try {
        MyAgent.getNameByNode("d");
    } catch (Exception e) {
        Assert.assertEquals("Failed to fetch data.", e.getMessage());
    }

Если написано так, когда не возникнет исключение, тест все равно пройдет . Именно этого мы хотим избежать в первую очередь
Кристиан Лим,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.