Mockito проверить после исключения Junit 4.10


я тестирую метод с ожидаемым исключением. Мне также нужно проверить, что какой-то код очистки был вызван (на издевательском объекте) после того, как возникло исключение, но похоже, что проверка игнорируется. Вот этот код. Я использую Junit ExpectedExceptionRule для проверки ожидаемого исключения.

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

@Test
public void testExpectedException()
{
   MockedObject mockObj = mock(MockedObj.class);
   MySubject subject = new MySubject(mockedObj);
   expectedEx.expect(MyException.class);
   expectedEx.expectMessage("My exception message.");
   subject.someMethodThrowingException();
   verify(mockObj).
       someCleanup(eq(...));
}

кажется verify полностью игнорируются. Независимо от того, какой метод я положил в verify, мой тест проходит, что не то, что я хотеть.

есть идеи, почему это происходит?

3 57

3 ответа:

ExpectedException произведения обертывание всего метода тестирования в блоке try-catch через JUnit @Rule. Когда ваш код создает исключение, он поднимается по стеку до ближайшего try/catch, который находится в экземпляре ExpectedException (который проверяет, что это исключение, которое вы ожидаете).

в Java, если в методе возникает неперехваченное исключение, управление никогда не вернется к операторам позже в этом методе. Здесь действуют те же правила: управление никогда не возвращается к операторам в тесте после исключения.

технически, вы можете поместить проверки в блок finally, но это, как правило,плохая привычка. В любом случае он, скорее всего, проглотит полезное ExpectedException сообщение, так как оно будет выполняться до того, как правило ExpectedException сможет перехватить его.

Если вам действительно нужно, чтобы проверить состояние после исключения, для каждого метода, вы всегда можете вернуться к этому идиома:

@Test
public void testExpectedException()
{
  MockedObject mockObj = mock(MockedObj.class);
  MySubject subject = new MySubject(mockedObj);
  try {
    subject.someMethodThrowingException();
    fail("Expected MyException.");
  } catch (MyException expected) {
    assertEquals("My exception message.", expected.getMessage());
  }
  verify(mockObj).someCleanup(eq(...));
}

обновление: С помощью лямбда-выражений Java 8 вы можете обернуть вызов функционального интерфейса в блок try достаточно кратко, чтобы быть полезным. Я предполагаю, что поддержка этого синтаксиса найдет свой путь во многих стандартных библиотеках тестирования.

assertThrows(MyException.class,
    () -> systemUnderTest.throwingMethod());

более элегантное решение с catch-exception

@Test
public void testExpectedException()
{
    MockedObject mockObj = mock(MockedObject.class);
    MySubject subject = new MySubject(mockObj);

    when(subject).someMethodThrowingException();

    then(caughtException())
            .isInstanceOf(MyException.class)
            .hasMessage("My exception message.");

    verify(mockObj).someCleanup(eq(...));
}

Я еще не пробовал это, но в дополнение к отличному ответу Джеффа Боумана у вас может быть выбор использовать правило ExpectedException с попыткой... наконец, конструкция, размещение вашего проверить инструкцию в блоке finally.