1. Общ преглед
Този урок показва как да използвате ArgumentMatcher и как той се различава от ArgumentCaptor .
За въведение в рамката на Mockito, моля, вижте тази статия.
2. Зависимости на Maven
Трябва да добавим един артефакт:
org.mockito mockito-core 2.21.0 test
Най-новата версия на Mockito може да бъде намерена в Maven Central .
3. ArgumentMatchers
Възможно е конфигуриране на подиграван метод по различни начини. Едно от тях е да върне фиксирани стойности:
doReturn("Flower").when(flowerService).analyze("poppy");
В горния пример String “Flower” се връща само когато услугата за анализ получи String “мак”.
Но може би трябва да отговорим на по-широк диапазон от стойности или предварително неизвестни стойности .
Във всички тези сценарии, можем да конфигурираме нашите подиграваха методи с аргумент кибрит :
when(flowerService.analyze(anyString())).thenReturn("Flower");
Сега, поради съвпадението на аргументи anyString , резултатът ще бъде същият, без значение каква стойност предаваме за анализ. ArgumentMatchers ни позволява гъвкава проверка или забиване.
В случай, че методът има повече от един аргумент, не е възможно да се използват ArgumentMatchers само за някои от аргументите . Mockito изисква да предоставите всички аргументи или чрез съвпадения, или чрез точни стойности.
Следващ пример е неправилен подход към това:
abstract class FlowerService { public abstract boolean isABigFlower(String name, int petals); } FlowerService mock = mock(FlowerService.class); when(mock.isABigFlower("poppy", anyInt())).thenReturn(true);
За да го поправим и да запазим името на String „мак“, както е желано, ще използваме eq matcher :
when(mock.isABigFlower(eq("poppy"), anyInt())).thenReturn(true);
Има още две точки, за които да се погрижите, когато се използват мачове :
- Не можем да ги използваме като стойност за връщане , точна стойност се изисква при забиване на обаждания
- И накрая, не можем да използваме съвпадения на аргументи извън проверка или забиване
В последния случай Mockito ще открие изгубения аргумент и ще хвърли InvalidUseOfMatchersException .
Лош пример може да бъде:
String orMatcher = or(eq("poppy"), endsWith("y")); verify(mock).analyze(orMatcher);
Начинът за изпълнение на горния код е:
verify(mock).analyze(or(eq("poppy"), endsWith("y")));
Mockito също така предоставя AdditionalMatchers за изпълнение на общи логически операции ('not', 'и', 'или') на ArgumentMatchers, които съответстват както на примитивни, така и на непримитивни типове:
verify(mock).analyze(or(eq("poppy"), endsWith("y")));
4. Съвпадение на потребителски аргументи
Създаването на нашето съвпадение може да бъде добре, за да изберете най-добрия възможен подход за даден сценарий и да направите тест с най-високо качество , който е чист и поддържаем.
Например, може да имаме MessageController, който доставя съобщения. Той ще получи MessageDTO и оттам ще създаде съобщение, което да бъде доставено от MessageService .
Нашата проверка ще бъде проста, проверете дали сме извикали MessageService точно 1 път с всяко съобщение:
verify(messageService, times(1)).deliverMessage(any(Message.class));
Тъй като Съобщението е изградено вътре в тествания метод , ние сме принудени да използваме всяко като съвпадение .
Този подход не ни позволява да проверяваме данните в съобщението , които могат да бъдат различни в сравнение с данните в MessageDTO .
Поради тази причина ще приложим съвпадение на потребителски аргументи:
public class MessageMatcher implements ArgumentMatcher { private Message left; // constructors @Override public boolean matches(Message right) { return left.getFrom().equals(right.getFrom()) && left.getTo().equals(right.getTo()) && left.getText().equals(right.getText()) && right.getDate() != null && right.getId() != null; } }
За да използваме нашето съвпадение, трябва да модифицираме нашия тест и да заменим всеки от argThat :
verify(messageService, times(1)).deliverMessage(argThat(new MessageMatcher(message)));
Сега знаем, че нашият екземпляр на Message ще има същите данни като нашия MessageDTO .
5. Съвпадение на потребителски аргументи срещу ArgumentCaptor
И двете техники за съвпадение на аргументи и ArgumentCaptor могат да се използват, за да се уверят, че определени аргументи са били предадени на макети.
Въпреки това, ArgumentCaptor може да бъде по-добър баланс, ако имаме нужда от него, за да отстояват по аргумент стойности за пълна проверка или нашия обичай аргумент за съотнасяне не може да се използва повторно .
Персонализираните аргументи за съвпадение чрез ArgumentMatcher обикновено са по-добри за потискане.
6. Заключение
В тази статия разгледахме характеристика на Mockito , ArgumentMatcher и разликата с ArgumentCaptor .
Както винаги, пълният изходен код на примерите е достъпен в GitHub.