EasyMock Argument Matchers
1. обзор
В этом руководстве мы исследуем сопоставление аргументов EasyMock. We’ll discuss different types of predefined matchers and how to create a custom matcher тоже.
Мы уже рассмотрели основы EasyMock в статьеintroduction to EasyMock, поэтому вам может потребоваться сначала прочитать ее, чтобы ознакомиться с EasyMock.
2. Простой пример насмешки
Прежде чем мы начнем изучать различные сопоставители, давайте взглянем на наш контекст. В этом руководстве мы будем использовать довольно простую пользовательскую службу в наших примерах.
Вот наш простой интерфейсIUserService:
public interface IUserService {
public boolean addUser(User user);
public List findByEmail(String email);
public List findByAge(double age);
}
И соответствующая модельUser:
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() для сопоставления с новым добавленнымUser:
@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);
}
Этот сопоставитель доступен как для примитивов, так и для объектов, а также дляuses the equals() method for objects.
Точно так же мы можем использовать сопоставлениеsame() для сопоставления определенногоUser:
@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);
}
The same() matcher compares arguments using “==”, что означает, что он сравнивает экземплярыUser в нашем случае.
Если мы не используем сопоставителей, аргументы по умолчанию сравниваются с использованиемequals().
Для массивов у нас также есть сопоставительaryEq(), который основан на методеArrays.equals().
Сопоставители4. Any
Есть несколько любых сопоставителей, таких какanyInt(),anyBoolean(),anyDouble() и т. Д. These specify that the argument should have the given type.
Давайте посмотрим на пример использованияanyString() для сопоставления ожидаемогоemail с любым значениемString:
@Test
public void givenUserService_whenSearchForUserByEmail_thenFound() {
expect(userService.findByEmail(anyString()))
.andReturn(Collections.emptyList());
replay(userService);
List result = userService.findByEmail("[email protected]");
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. Нулевые сопоставители
Далееwe can use the isNull() and notNull() matchers to match null values.
В следующем примере мы будем использовать сопоставительisNull() для сопоставления, если добавленное значениеUser равно нулю:
@Test
public void givenUserService_whenAddNull_thenFail() {
expect(userService.addUser(isNull())).andReturn(false);
replay(userService);
boolean result = userService.addUser(null);
verify(userService);
assertFalse(result);
}
Мы также можем сопоставитьnotNull(), если добавленное значение пользователя не равно нулю, аналогичным образом:
@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. String
Есть несколько полезных сопоставителей, которые мы можем использовать с аргументамиString.
Во-первых, мы будем использовать сопоставительstartsWith(), чтобы сопоставить префикс электронной почты пользователя:
@Test
public void whenSearchForUserByEmailStartsWith_thenFound() {
expect(userService.findByEmail(startsWith("test")))
.andReturn(Collections.emptyList());
replay(userService);
List result = userService.findByEmail("[email protected]");
verify(userService);
assertEquals(0,result.size());
}
Точно так же мы будем использовать сопоставительendsWith() для суффикса электронной почты:
@Test
public void givenUserService_whenSearchForUserByEmailEndsWith_thenFound() {
expect(userService.findByEmail(endsWith(".com")))
.andReturn(Collections.emptyList());
replay(userService);
List result = userService.findByEmail("[email protected]");
verify(userService);
assertEquals(0,result.size());
}
В более общем смысле мы можем использоватьcontains() для сопоставления электронного письма с заданной подстрокой:
@Test
public void givenUserService_whenSearchForUserByEmailContains_thenFound() {
expect(userService.findByEmail(contains("@")))
.andReturn(Collections.emptyList());
replay(userService);
List result = userService.findByEmail("[email protected]");
verify(userService);
assertEquals(0,result.size());
}
Или даже сопоставьте наш адрес электронной почты с определенным регулярным выражением, используяmatches():
@Test
public void givenUserService_whenSearchForUserByEmailMatches_thenFound() {
expect(userService.findByEmail(matches(".+\\@.+\\..+")))
.andReturn(Collections.emptyList());
replay(userService);
List result = userService.findByEmail("[email protected]");
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 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 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 result = userService.findByAge(20);
verify(userService);
assertEquals(0,result.size());
}
Другой пример, который мы можем рассмотреть, - это объединениеnot() сendsWith() для сопоставления писем, которые не заканчиваются на «.com»:
@Test
public void givenUserService_whenSearchForUserByEmailNotEndsWith_thenFound() {
expect(userService.findByEmail(not(endsWith(".com"))))
.andReturn(Collections.emptyList());
replay(userService);
List result = userService.findByEmail("[email protected]");
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 result = userService.findByEmail("[email protected]");
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 имеет два метода:matches() иappendTo().
Первый метод содержит проверку аргументов и логику для нашего сопоставителя, а второй используется для добавления представления сопоставленияString, которое будет напечатано в случае сбоя.
10. Заключение
Мы рассмотрели предопределенные сопоставления аргументов EasyMock для разных типов данных и способы их создания.
Полный исходный код примеров доступенover on GitHub.