Метод повторной заглушки Mockito уже прошит с помощью заглушки

У меня возникла проблема с mockito. Я разрабатываю веб-приложение. В моих тестах имитируется управление пользователями. В некоторых случаях мне нужно изменить пользователя, возвращаемого методом getLoggedInUser().

Проблема в том, что мой метод getLoggedInUser() также может выдавать AuthenticationException.

Поэтому, когда я пытаюсь переключиться с одного пользователя на другого, вызов

when(userProvider.getLoggedInUser()).thenReturn(user);

выдает исключение, поскольку userProvider.getLoggedInUser() уже заглушен thenTrow()

Есть ли способ указать методу when не заботиться об исключениях?

Заранее спасибо - Иштван


person Sobvan    schedule 14.11.2010    source источник
comment
Спасибо, ребята, за ответы! Подводя итог: вероятно, из-за плохого дизайна программного обеспечения мне нужно перезапустить метод. Но пока мне это легко, да и тесты выглядят чисто. Я провел еще несколько исследований и нашел метод Mockito.reset (T ... mocks), который помогает мне. В следующий раз придумаю более простой дизайн :)   -  person Sobvan    schedule 16.11.2010


Ответы (3)


Моя первая реакция на ваш вопрос - это похоже на то, что вы пытаетесь сделать слишком много за один тест.

Для простоты тестирования и простоты каждый тест должен проверять только одно. Это то же самое, что и принцип единой ответственности. Я часто замечаю, что программисты пытаются протестировать несколько вещей в одном тесте и из-за этого сталкиваются со всевозможными проблемами. Итак, каждый из ваших методов модульного тестирования должен следовать этой последовательности:

  1. Настройте единый сценарий для теста.
  2. Сделайте вызов тестируемого класса, чтобы запустить тестируемый код.
  3. Проверьте поведение.

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

Вторая мысль, которая приходит в голову, - это не заглушить. Попробуйте вместо этого использовать expect, потому что вы можете настроить серию ожиданий. Т.е. первый вызов возвращает пользователя, второй вызов вызывает исключение, третий вызов возвращает другого пользователя и т. д.

person drekka    schedule 14.11.2010
comment
Будем признательны за пример использования 'expect' или ссылку на документацию / учебные пособия :) - person Abimbola Esuruoso; 27.12.2014

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

when(mock.someMethod("some arg"))
    .thenThrow(new RuntimeException())
    .thenReturn("foo");

https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#10

person Bogdan Sulima    schedule 14.06.2012

Есть ли способ указать методу when не заботиться об исключениях?

Чтобы ответить на этот вопрос:

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;

import org.junit.Test;
import org.mockito.Mockito;

import java.util.ArrayList;

public class MyTest {

    @Test
    public void testA() {

        // setup
        ArrayList<Object> list = mock(ObjectArrayList.class);
        when(list.indexOf(any())).thenReturn(6);
        when(list.indexOf(any())).thenReturn(12);

        // execute
        int index = list.indexOf(new Object());

        // verify
        assertThat(index, is(equalTo(12)));
    }

    @Test
    public void testB() {

        // setup
        ArrayList<Object> list = mock(ObjectArrayList.class);
        when(list.add(any())).thenThrow(new AssertionError("can't get rid of me!"));
        when(list.add(any())).thenReturn(true);

        // execute
        list.add(new Object());
    }

    @Test
    public void testC() {

        // setup
        ArrayList<Object> list = mock(ObjectArrayList.class);
        when(list.add(any())).thenThrow(new AssertionError("can't get rid of me!"));
        Mockito.reset(list);
        when(list.add(any())).thenReturn(true);

        // execute
        list.add(new Object());
    }

    /**
     * Exists to work around the fact that mocking an ArrayList<Object>
     * requires a cast, which causes "unchecked" warnings, that can only be suppressed...
     */
    class ObjectArrayList extends ArrayList<Object> {

    }
}

TestB терпит неудачу из-за утверждения, от которого вы не можете избавиться. TestC показывает, как можно использовать метод reset для сброса макета и удаления на нем команды thenThrow.

Обратите внимание, что сброс не всегда работает в некоторых более сложных примерах, которые у меня есть. Я подозреваю, что это может быть потому, что они используют PowerMockito.mock, а не Mockito.mock?

person Pod    schedule 11.05.2017