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

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

@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 ответов


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

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

технически вы можете поместить проверки в блок 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 с попыткой... наконец, создайте, разместив оператор verify в блоке finally.