Мокито - Использование шпионов
1. обзор
В этом руководстве мы покажем, как максимально эффективно использоватьspies in Mockito.
Мы поговорим об аннотации@Spy, как заглушить шпиона и, наконец, мы рассмотрим разницу междуMock иSpy.
И, конечно же, для большего удовольствия от Mockito,have a look at the series here.
Дальнейшее чтение:
Инъекция Mockito Mocks в бобы
В этой статье будет показано, как использовать внедрение зависимостей для вставки макетов Mockito в Spring Beans для модульного тестирования.
Mockito Mock Методы
Это руководство иллюстрирует различные способы использования стандартных статических методов Mockito API.
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.