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, погледнете поредицата тук.