Мокито - Использование шпионов

Мокито - Использование шпионов

1. обзор

В этом руководстве мы покажем, как максимально эффективно использоватьspies in Mockito.

Мы поговорим об аннотации@Spy, как заглушить шпиона и, наконец, мы рассмотрим разницу междуMock иSpy.

И, конечно же, для большего удовольствия от Mockito,have a look at the series here.

Дальнейшее чтение:

Mockito Verify Поваренная книга

Примеры, использование и лучшие практикиMockito Verify.

Read more

Инъекция Mockito Mocks в бобы

В этой статье будет показано, как использовать внедрение зависимостей для вставки макетов Mockito в Spring Beans для модульного тестирования.

Read more

Mockito Mock Методы

Это руководство иллюстрирует различные способы использования стандартных статических методов Mockito API.

Read more

2. Простой примерSpy

Начнем с простого примераhow to use a spy.

Проще говоря, API отMockito.spy() доspy on a real object.

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

Хорошо, давайте сделаем быстрый пример, в котором мы будем следить за существующим объектомArrayList:

@Test
public void whenSpyingOnList_thenCorrect() {
    List list = new ArrayList();
    List spyList = Mockito.spy(list);

    spyList.add("one");
    spyList.add("two");

    Mockito.verify(spyList).add("one");
    Mockito.verify(spyList).add("two");

    assertEquals(2, spyList.size());
}

Обратите внимание, какthe real method add() is actually called и как размерspyList становится равным 2.

3. Аннотация@Spy

Далее - давайте посмотрим, как использовать аннотацию@Spy. Мы можем использовать аннотацию@Spy вместоspy(), как в следующем примере:

@Spy
List spyList = new ArrayList();

@Test
public void whenUsingTheSpyAnnotation_thenObjectIsSpied() {
    spyList.add("one");
    spyList.add("two");

    Mockito.verify(spyList).add("one");
    Mockito.verify(spyList).add("two");

    assertEquals(2, spyList.size());
}

Чтобыenable Mockito annotation (например,@Spy,@Mock,…), нам нужно сделать одно из следующих действий:

  • Вызовите методMockitoAnnotations.initMocks(this) для инициализации аннотированных полей

  • Используйте встроенный бегун@RunWith(MockitoJUnitRunner.class)

4. Заглушка aSpy

Теперь - давайте посмотрим, как заглушитьSpy. Мы можем настроить / переопределить поведение метода, используя тот же синтаксис, который мы использовали бы с макетом.

В следующем примере - мы используемdoReturn() для переопределения методаsize():

@Test
public void whenStubASpy_thenStubbed() {
    List list = new ArrayList();
    List spyList = Mockito.spy(list);

    assertEquals(0, spyList.size());

    Mockito.doReturn(100).when(spyList).size();
    assertEquals(100, spyList.size());
}

5. Mock vs. Spy in Mockito

А теперь давайте обсудим разницу междуMock иSpy в Mockito, а не теоретические различия между двумя концепциями, а просто то, как они различаются внутри самого Mockito.

Когда Mockito создает макет - он делает это изClass типа, а не из фактического экземпляра. Мок просто создаетa bare-bones shell instance класса, полностью оборудованный для отслеживания взаимодействия с ним.

С другой стороны,the spy will wrap an existing instance. Он по-прежнему будет вести себя так же, как и обычный экземпляр, с той лишь разницей, что он также будет оснащен инструментами для отслеживания всех взаимодействий с ним.

В следующем примере мы создаемmock классаArrayList:

@Test
public void whenCreateMock_thenCreated() {
    List mockedList = Mockito.mock(ArrayList.class);

    mockedList.add("one");
    Mockito.verify(mockedList).add("one");

    assertEquals(0, mockedList.size());
}

Как мы видим, добавление элемента в список имитаций на самом деле ничего не добавляет - оно просто вызывает метод без каких-либо других побочных эффектов.

С другой стороны, шпион будет вести себя иначе - он фактически вызовет реальную реализацию методаadd и добавит элемент в базовый список:

@Test
public void whenCreateSpy_thenCreate() {
    List spyList = Mockito.spy(new ArrayList());

    spyList.add("one");
    Mockito.verify(spyList).add("one");

    assertEquals(1, spyList.size());
}

6. Понимание MockitoNotAMockException

В этом последнем разделе мы узнаем о MockitoNotAMockException. This exception is one of the common exceptions we will likely encounter when misusing mocks or spies.

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

List list = new ArrayList();
Mockito.doReturn(100).when(list).size();

assertEquals("Size should be 100: ", 100, list.size());

Когда мы запустим этот фрагмент кода, мы получим следующую ошибку:

org.mockito.exceptions.misusing.NotAMockException:
Argument passed to when() is not a mock!
Example of correct stubbing:
    doThrow(new RuntimeException()).when(mock).someMethod();

К счастью, из сообщения об ошибке Mockito совершенно ясно, в чем проблема. В нашем примере объектlist не является имитацией. The Mockito when() method expects a mock or spy object as the argument.

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

final List spyList = Mockito.spy(new ArrayList());
Mockito.doReturn(100).when(spyList).size();

assertEquals("Size should be 100: ", 100, spyList.size());

Наш пример теперь ведет себя так, как ожидалось, и мы больше не видим MockitoNotAMockException.

7. Заключение

В этой быстрой статье мы обсудили наиболее полезные примеры использования шпионов Мокито.

Мы узнали, как создатьspy, как использовать аннотацию@Spy, как заглушитьspy и, наконец, - разницу междуMock иSpy.

Реализация всех этих примеровcan be found over on GitHub.

Это проект Maven, поэтому его легко импортировать и запускать как есть.

И, конечно же, для большего удовольствия от Mockito,have a look at the series here.