EasyMock Аргументы соответствия

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.