Mockito - Използване на шпиони

1. Общ преглед

В този урок ще илюстрираме как да се възползваме максимално от шпионите в Mockito .

Ще говорим за анотацията @Spy , как да смажем шпионин и накрая - ще навлезем в разликата между Mock и Spy .

И разбира се, за повече доброта на Mockito, погледнете поредицата тук.

2. Прост пример за шпионин

Нека започнем с прост пример за това как да използваме шпионин .

Най-просто казано, API е Mockito.spy () - за шпиониране на реален обект .

Това ще ни позволи да извикаме всички нормални методи на обекта, като същевременно проследяваме всяко взаимодействие, точно както бихме направили с макет.

Добре, нека направим бърз пример, където ще шпионираме съществуващ обект 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()); }

Обърнете внимание как всъщност се извиква реалният метод add () и как размерът на 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()); }

За да активираме анотацията на Mockito (като @Spy , @Mock , ...) - трябва да направим едно от следните:

  • Извикайте метода MockitoAnnotations.initMocks (този), за да инициализирате коментирани полета
  • Използвайте вградения бегач @RunWith (MockitoJUnitRunner.class)

4. Намушкване на шпионин

Сега - да видим как да смажем шпионин . Можем да конфигурираме / заменим поведението на метод, използвайки същия синтаксис, който бихме използвали с макет.

В следния пример - използваме 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 в Mockito

Сега - нека да обсъдим разликата между Mock и Spy в Mockito - а не теоретичните разлики между двете концепции, просто как те се различават в самия Mockito.

Когато Mockito създава макет - той го прави от Класа на Тип, а не от действителен екземпляр. Подигравката просто създава екземпляр от черупки с голи кости на класа, изцяло инструментиран да проследява взаимодействията с него.

От друга страна, шпионинът ще обгърне съществуващ екземпляр . Той ще продължи да се държи по същия начин като нормалния екземпляр - единствената разлика е, че той също ще бъде инструментиран да проследява всички взаимодействия с него.

В следния пример - ние създаваме макет на класа 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. Разбиране на Mockito NotAMockException

В този последен раздел ще научим за Mockito NotAMockException . Това изключение е едно от често срещаните изключения, които вероятно ще срещнем при злоупотреба с макети или шпиони .

Нека започнем, като видим при какви обстоятелства може да възникне това изключение:

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 е съвсем ясно какъв е проблемът тук. В нашия пример обектът на списъка не е фалшив. Методът Mockito when () очаква като аргумент макет или шпионски обект .

Както виждаме, съобщението за изключение дори описва как трябва да изглежда правилното извикване. Сега, след като разбрахме по-добре какъв е проблемът, нека го поправим, като следваме препоръката:

final List spyList = Mockito.spy(new ArrayList()); Mockito.doReturn(100).when(spyList).size(); assertEquals("Size should be 100: ", 100, spyList.size()); 

Нашият пример сега се държи според очакванията и вече не виждаме Mockito NotAMockException.

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

В тази кратка статия обсъдихме най-полезните примери за използване на шпиони на Mockito.

Научихме как да създадем шпионин , как да използваме @Spy анотация, как да смажем шпионин и накрая - разликата между Mock и Spy .

Изпълнението на всички тези примери може да бъде намерено в GitHub .

Това е проект на Maven, така че трябва да е лесно да се импортира и да се изпълнява както е.

И разбира се, за повече доброта на Mockito, погледнете поредицата тук.