1. Обзор

Hamcrest — это библиотека, предоставляющая методы, называемые сопоставителями, которые помогают разработчикам писать более простые модульные тесты. Есть много совпадений, вы можете начать, прочитав о некоторых из них здесь.

В этой статье мы рассмотрим сопоставители бобов.

2. Настройка

Чтобы получить Hamcrest, нам просто нужно добавить следующую зависимость Maven в наш pom.xml:

Последнюю версию Hamcrest можно найти на Maven Central.

<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>java-hamcrest</artifactId>
    <version>2.0.0.0</version>
    <scope>test</scope>
</dependency>

3. Сопоставители бинов

Сопоставители бинов чрезвычайно полезны для проверки условий над POJO, что часто требуется при написании большинства модульных тестов.

Прежде чем начать, мы создадим класс, который поможет нам в примерах:

Теперь, когда все готово, давайте посмотрим, как работают сопоставители бобов!

public class City {
    String name;
    String state;

    // standard constructor, getters and setters

}

3.1. hasProperty

Этот сопоставитель в основном проверяет, содержит ли определенный bean-компонент определенное свойство, идентифицируемое по имени свойства:

Итак, этот тест будет пройден, потому что наш bean-компонент City имеет свойство с именем state.

@Test
public void givenACity_whenHasProperty_thenCorrect() {
    City city = new City("San Francisco", "CA");
    
    assertThat(city, hasProperty("state"));
}

Следуя этой идее, мы также можем проверить, имеет ли бин определенное свойство и это свойство имеет определенное значение:

Как мы видим, hasProperty перегружен и может использоваться со вторым сопоставителем для проверки конкретного состояние над имуществом.

@Test
public void givenACity_whenHasPropertyWithValueEqualTo_thenCorrect() {
    City city = new City("San Francisco", "CA");
        
    assertThat(city, hasProperty("name", equalTo("San Francisco")));
}

Итак, мы также можем сделать это:

Полезно, правда? Мы можем продвинуть эту идею еще на один шаг вперед с помощью сопоставителя, который мы рассмотрим далее.

@Test
public void givenACity_whenHasPropertyWithValueEqualToIgnoringCase_thenCorrect() {
    City city = new City("San Francisco", "CA");

    assertThat(city, hasProperty("state", equalToIgnoringCase("ca")));
}

3.2. samePropertyValuesAs

Иногда, когда нам нужно проверить множество свойств бина, может быть проще создать новый бин с нужными значениями. Затем мы можем проверить равенство между тестируемым компонентом и новым. Конечно, Hamcrest предоставляет сопоставитель для этой ситуации:

Это приводит к меньшему количеству утверждений и более простому коду. Точно так же мы можем протестировать отрицательный случай:

@Test
public void givenACity_whenSamePropertyValuesAs_thenCorrect() {
    City city = new City("San Francisco", "CA");
    City city2 = new City("San Francisco", "CA");

    assertThat(city, samePropertyValuesAs(city2));
}

Далее рассмотрим пару util-методов для проверки свойств класса.

@Test
public void givenACity_whenNotSamePropertyValuesAs_thenCorrect() {
    City city = new City("San Francisco", "CA");
    City city2 = new City("Los Angeles", "CA");

    assertThat(city, not(samePropertyValuesAs(city2)));
}

3.3. getPropertyDescriptor

Существуют сценарии, когда может пригодиться возможность исследовать структуру класса. Для этого Hamcrest предоставляет несколько вспомогательных методов:

Дескриптор объекта извлекает много информации о состоянии свойства. В этом случае мы извлекли имя геттера и утверждаем, что оно равно некоторому ожидаемому значению. Обратите внимание, что мы также можем применять другие средства сопоставления текста.

@Test
public void givenACity_whenGetPropertyDescriptor_thenCorrect() {
    City city = new City("San Francisco", "CA");
    PropertyDescriptor descriptor = getPropertyDescriptor("state", city);

    assertThat(descriptor
      .getReadMethod()
      .getName(), is(equalTo("getState")));
}

Двигаемся дальше, последний метод, который мы рассмотрим, является более общим случаем той же самой идеи.

3.4. propertyDescriptorsFor

Этот метод делает то же самое, что и в предыдущем разделе, но для всех свойств компонента. Нам также нужно указать, как высоко мы хотим подняться в иерархии классов:

Итак, что мы сделали здесь: получили все дескрипторы свойств из bean city и остановились на уровне объекта.

@Test
public void givenACity_whenGetPropertyDescriptorsFor_thenCorrect() {
    City city = new City("San Francisco", "CA");
    PropertyDescriptor[] descriptors = propertyDescriptorsFor(
      city, Object.class);
 
    List<String> getters = Arrays.stream(descriptors)
      .map(x -> x.getReadMethod().getName())
      .collect(toList());

    assertThat(getters, containsInAnyOrder("getName", "getState"));
}

Затем мы просто использовали возможности Java 8 для фильтрации методов получения.

Наконец, мы использовали сопоставители коллекций, чтобы проверить что-то в списке геттеров. Вы можете найти больше информации о сопоставлениях коллекций здесь.

4. Заключение

Сопоставители Hamcrest состоят из большого набора инструментов, которые можно использовать в каждом проекте. Их легко освоить, и они становятся чрезвычайно полезными за короткое время.

Сопоставители бинов, в частности, обеспечивают эффективный способ создания утверждений над POJO, что часто требуется при написании модульных тестов.

Чтобы получить полную реализацию этих примеров, обратитесь к проекту GitHub.

«