Подтвердить что ты не робот

Как высмеять метод возврата void, влияющий на объект

Я пишу модульные тесты для своего приложения, и мне было интересно, возможно ли, чтобы структура Mockito влияла на объект, который передается в метод, который возвращает пустоту из издевающегося класса. Например, вызывая издевательский класс проверки, содержащий метод, который возвращает void, но отслеживает различные изменения и метаданные через объект, переданный в качестве аргумента..

public GetCartItemsOutput getCartItems(GetCartItemsInput getCartItemsInput) {
    CartItemsFilter cartItemsFilter = new CartItemsFilter();
    validator.validateCartItemsInput(getCartItemsInput, cartItemsFilter); ...

Я издевался над классом валидатора для других моих тестов, но для этого мне нужно mock изменения в объекте cartItemsFilter, который я не знаю, как это сделать.

4b9b3361

Ответ 1

Ответ - да, вы можете, и в основном есть два уровня выполнения этого, основанные на необходимости вашего теста.

Если вы просто хотите проверить взаимодействие с имитируемым объектом, вы можете просто использовать метод verify(), чтобы убедиться, что был вызван метод void.

Если вашему тесту действительно нужен смоделированный объект для изменения переданных ему параметров, вам необходимо реализовать Answer:

Отредактировано, чтобы показать правильную форму использования ответа с пустым методом

doAnswer(new Answer() {
    @Override
    Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        ((MyClass)args[0]).myClassSetMyField(NEW_VALUE);
        return null; // void method, so return null
    }
}).when(mock).someMethod();

В Java 8+ вышеупомянутое упрощено с помощью лямбды:

doAnswer(invocation-> {
    Object[] args = invocation.getArguments();
    ((MyClass)args[0]).myClassSetMyField(NEW_VALUE);
    return null;
}).when(mock).someMethod();

Ответ 2

Чтобы добавить к Кевину Уэлкеру ответ, если ваш MyClass является настраиваемым классом, тогда определите в нем метод equals/hashcode, так что Mockito может использовать его для соответствия точному вызову метода.

В моем случае "MyClass" был в стороннем API, поэтому мне пришлось использовать метод "any", как показано ниже -

 doAnswer(new Answer() {
    Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        ((MyClass)args[0]).myClassSetMyField(NEW_VALUE);
        return null; // void method, so return null
    }
}).when(mock).someMethod(any(MyClass.class));

Ответ 3

Также может помочь ArgumentCaptor.

Здесь фрагмент найден из здесь:

  ArgumentCaptor<GetCartItemsInput > argument = ArgumentCaptor.forClass(GetCartItemsInput .class);
  verify(mock).getCartItems(argument.capture());
  assertEquals(cartItemsFilter, argument.getValue());