1. Обзор
В этом руководстве мы рассмотрим средства сопоставления аргументов EasyMock. Мы обсудим различные типы предопределенных сопоставителей, а также то, как создать собственный сопоставитель.
Мы уже рассмотрели основы EasyMock во введении к статье EasyMock, поэтому вам, возможно, придется сначала прочитать ее, чтобы ознакомиться с EasyMock.
2. Простой насмешливый пример
Прежде чем мы начнем изучать различные сопоставители, давайте взглянем на наш контекст. На протяжении всего этого руководства мы будем использовать в наших примерах довольно простой пользовательский сервис.
Вот наш простой интерфейс IUserService
:
public interface IUserService {
public boolean addUser(User user);
public List<User> findByEmail(String email);
public List<User> findByAge(double age);
}
И связанная модель пользователя :
public class User {
private long id;
private String firstName;
private String lastName;
private double age;
private String email;
// standard constructor, getters, setters
}
Итак, мы начнем просто с макета нашего IUserService
, чтобы использовать его в наших примерах:
private IUserService userService = mock(IUserService.class);
Теперь давайте рассмотрим средства сопоставления аргументов EasyMock.
3. Сопоставители равенства
Во- первых, мы будем использовать сопоставитель eq()
для сопоставления с новым добавленным пользователем
:
@Test
public void givenUserService_whenAddNewUser_thenOK() {
expect(userService.addUser(eq(new User()))).andReturn(true);
replay(userService);
boolean result = userService.addUser(new User());
verify(userService);
assertTrue(result);
}
Этот сопоставитель доступен как для примитивов, так и для объектов, и использует метод equals()
для объектов .
Точно так же мы можем использовать сопоставитель same()
для сопоставления с конкретным пользователем
:
@Test
public void givenUserService_whenAddSpecificUser_thenOK() {
User user = new User();
expect(userService.addUser(same(user))).andReturn(true);
replay(userService);
boolean result = userService.addUser(user);
verify(userService);
assertTrue(result);
}
Сопоставитель same()
сравнивает аргументы, используя « == »
, что означает, что в нашем случае он сравнивает экземпляры пользователя .
Если мы не используем никаких сопоставителей, аргументы по умолчанию сравниваются с использованием equals().
Для массивов у нас также есть сопоставитель aryEq()
, основанный на методе Arrays.equals()
.
4. Любые совпадения
Существует несколько любых сопоставителей, таких как anyInt()
, anyBoolean()
, anyDouble()
,… и т. д. Они указывают, что аргумент должен иметь заданный тип.
Давайте посмотрим на пример использования anyString()
для сопоставления ожидаемого электронного письма
с любым строковым
значением:
@Test
public void givenUserService_whenSearchForUserByEmail_thenFound() {
expect(userService.findByEmail(anyString()))
.andReturn(Collections.emptyList());
replay(userService);
List<User> result = userService.findByEmail("test@example.com");
verify(userService);
assertEquals(0,result.size());
}
Мы также можем использовать isA()
для сопоставления аргумента с экземпляром определенного класса:
@Test
public void givenUserService_whenAddUser_thenOK() {
expect(userService.addUser(isA(User.class))).andReturn(true);
replay(userService);
boolean result = userService.addUser(new User());
verify(userService);
assertTrue(result);
}
Здесь мы утверждаем, что ожидаем, что параметр метода addUser()
будет иметь тип User.
5. Нулевые совпадения
Затем мы можем использовать сопоставители isNull()
и notNull()
для сопоставления нулевых
значений.
В следующем примере мы будем использовать сопоставитель isNull()
для сопоставления, если добавленное значение User
равно null:
@Test
public void givenUserService_whenAddNull_thenFail() {
expect(userService.addUser(isNull())).andReturn(false);
replay(userService);
boolean result = userService.addUser(null);
verify(userService);
assertFalse(result);
}
Мы также можем использовать notNull()
для сопоставления, если добавленное пользовательское значение не равно null, аналогичным образом:
@Test
public void givenUserService_whenAddNotNull_thenOK() {
expect(userService.addUser(notNull())).andReturn(true);
replay(userService);
boolean result = userService.addUser(new User());
verify(userService);
assertTrue(result);
}
6. Сопоставители строк
Есть несколько полезных сопоставителей, которые мы можем использовать со строковыми
аргументами.
Во-первых, мы будем использовать сопоставитель startWith()
для сопоставления префикса электронной почты пользователя:
@Test
public void whenSearchForUserByEmailStartsWith_thenFound() {
expect(userService.findByEmail(startsWith("test")))
.andReturn(Collections.emptyList());
replay(userService);
List<User> result = userService.findByEmail("test@example.com");
verify(userService);
assertEquals(0,result.size());
}
Точно так же мы будем использовать сопоставитель endWith()
для суффикса электронной почты:
@Test
public void givenUserService_whenSearchForUserByEmailEndsWith_thenFound() {
expect(userService.findByEmail(endsWith(".com")))
.andReturn(Collections.emptyList());
replay(userService);
List<User> result = userService.findByEmail("test@example.com");
verify(userService);
assertEquals(0,result.size());
}
В более общем случае мы можем использовать contains()
для сопоставления электронной почты с заданной подстрокой:
@Test
public void givenUserService_whenSearchForUserByEmailContains_thenFound() {
expect(userService.findByEmail(contains("@")))
.andReturn(Collections.emptyList());
replay(userService);
List<User> result = userService.findByEmail("test@example.com");
verify(userService);
assertEquals(0,result.size());
}
Или даже сопоставьте нашу электронную почту с определенным регулярным выражением, используя match ()
:
@Test
public void givenUserService_whenSearchForUserByEmailMatches_thenFound() {
expect(userService.findByEmail(matches(".+\\@.+\\..+")))
.andReturn(Collections.emptyList());
replay(userService);
List<User> result = userService.findByEmail("test@example.com");
verify(userService);
assertEquals(0,result.size());
}
7. Сопоставители чисел
У нас также есть несколько сопоставителей для числовых значений, которые мы можем использовать.
Давайте посмотрим на пример использования сопоставителя lt()
для сопоставления аргумента age с значением меньше 100:
@Test
public void givenUserService_whenSearchForUserByAgeLessThan_thenFound() {
expect(userService.findByAge(lt(100.0)))
.andReturn(Collections.emptyList());
replay(userService);
List<User> result = userService.findByAge(20);
verify(userService);
assertEquals(0,result.size());
}
Точно так же мы также используем geq()
, чтобы аргумент age был больше или равен 10:
@Test
public void givenUserService_whenSearchForUserByAgeGreaterThan_thenFound() {
expect(userService.findByAge(geq(10.0)))
.andReturn(Collections.emptyList());
replay(userService);
List<User> result = userService.findByAge(20);
verify(userService);
assertEquals(0,result.size());
}
Доступные средства сопоставления чисел:
lt()
– меньше заданного значенияleq()
– меньше или равноgt()
– больше, чемgeq()
— больше или равно
8. Комбинируйте матчеры
Мы также можем комбинировать несколько сопоставителей, используя сопоставители and()
, or()
и not()
.
Давайте посмотрим, как мы можем объединить два сопоставителя, чтобы убедиться, что значение возраста больше 10 и меньше 100:
@Test
public void givenUserService_whenSearchForUserByAgeRange_thenFound() {
expect(userService.findByAge(and(gt(10.0),lt(100.0))))
.andReturn(Collections.emptyList());
replay(userService);
List<User> result = userService.findByAge(20);
verify(userService);
assertEquals(0,result.size());
}
Другой пример, на который мы можем обратить внимание, — это комбинация not()
с endWith()
для сопоставления адресов электронной почты, которые не заканчиваются на «.com»:
@Test
public void givenUserService_whenSearchForUserByEmailNotEndsWith_thenFound() {
expect(userService.findByEmail(not(endsWith(".com"))))
.andReturn(Collections.emptyList());
replay(userService);
List<User> result = userService.findByEmail("test@example.org");
verify(userService);
assertEquals(0,result.size());
}
9. Пользовательский матчер
Наконец, мы обсудим, как создать собственный сопоставитель EasyMock.
Цель состоит в том, чтобы создать простой сопоставитель minCharCount()
для сопоставления строк с длиной, большей или равной заданному значению:
@Test
public void givenUserService_whenSearchForUserByEmailCharCount_thenFound() {
expect(userService.findByEmail(minCharCount(5)))
.andReturn(Collections.emptyList());
replay(userService);
List<User> result = userService.findByEmail("test@example.com");
verify(userService);
assertEquals(0,result.size());
}
Чтобы создать собственный сопоставитель аргументов, нам необходимо:
- создайте новый класс, реализующий интерфейс
IArgumentMatcher
- создайте статический метод с новым именем сопоставления и зарегистрируйте экземпляр класса выше, используя
reportMatcher()
Давайте посмотрим на оба шага в нашем методе minCharCount()
, в котором объявляется анонимный класс:
public static String minCharCount(int value){
EasyMock.reportMatcher(new IArgumentMatcher() {
@Override
public boolean matches(Object argument) {
return argument instanceof String
&& ((String) argument).length() >= value;
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("charCount(\"" + value + "\")");
}
});
return null;
}
Также обратите внимание, что интерфейс IArgumentMatcher
имеет два метода: match( )
и appendTo().
Первый метод содержит проверку аргументов и логику для нашего сопоставителя, а второй используется для добавления строкового представления
сопоставителя , которое будет напечатано в случае сбоя.
10. Заключение
Мы рассмотрели предопределенные средства сопоставления аргументов EasyMock для различных типов данных и способы создания нашего собственного средства сопоставления.
Полный исходный код примеров доступен на GitHub .