Как проверить вызов метода, который находится в конструкторе?

1

У меня есть конструктор, который вызывает вызов двум методам. Они оба недействительны, и я просто хочу проверить, что они вызваны.

Foo.java

public class Foo {

    public Foo(String name, Object obj) {
         init(name);
         doSomething(obj);
    }
}

FooTest.java

@Test
public void constructor_test throws Exception {
    Foo foo = Mockito.mock(Foo.class);
    PowerMockito.whenNew(Foo.class).withAnyArguments().thenReturn(foo);
    Foo f = new Foo("name");
    verify(f).init(Mockito.anyString()); 
    verify(f).doSomething(Mockito.any(Object.class)); 
}

Единичный тест завершился неудачей с сообщением о том, что было нулевое взаимодействие с mock foo.init(); ,

Как проверить вызов метода, который находится внутри конструктора?

  • 2
    Вы действительно должны использовать насмешку в этом случае? Если эти методы изменяют состояние Foo , лучше проверить это состояние. Если они вызывают некоторые внешние компоненты, вы можете вместо этого смоделировать эти компоненты.
Теги:
unit-testing
powermock
junit
mockito

1 ответ

4
Лучший ответ

Не можете ли вы проверить, проверяя состояние вашего Foo?

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

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

Если эти методы взаимодействуют с некоторыми внешними компонентами, вы можете издеваться над этими компонентами, как обычно, с любым методом, а затем проверять взаимодействие так, как вы ожидаете. Независимо от того, происходит ли это взаимодействие в том или ином виде внутри, должно быть частью реализации класса Foo и извне вам все равно.

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

Что касается вашего фактического вопроса, я не уверен, что вы можете делать то, что хотите, поскольку, по моему мнению, ваш Foo не является "настоящим" Foo а макетным Foo поэтому реальный конструктор не будет вызван.

Если вы в состоянии это сделать, это создать "PartialMock" и передать его в базовый класс. У меня только небольшой опыт работы с Mockito, но я думаю, что этот подход может быть возможен в некоторых других (.NET) смешных фреймворках, с которыми я знаком, хотя я их не пробовал, но он может дать вам дополнительные слова для активируйте свой google foo.

  • 0
    Спасибо. Причины, по которым не следует создавать фиктивный объект, имеют смысл. Я получил прохождение модульного теста, утверждая, что состояние объекта соответствует тому, что я ожидал.
  • 2
    @ Джей, это отлично. Ваши тесты всегда будут лучше, если они не зависят от того, как реализуется тестируемая вещь, и вместо этого полагаются на поведение / состояние для проверки своих ожиданий, ИМХО. Макеты должны быть последним средством тестирования, а не первым портом вызова, и каждый макет представляет связь, что означает, что когда вы хотите изменить поведение классов, вы должны изменить его и в тесте.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню