Спеціальні матчери Hamcrest

1. Вступ

Окрім вбудованих збігів, Hamcrest також надає підтримку для створення спеціальних збігів.

У цьому підручнику ми детальніше розглянемо, як їх створювати та використовувати. Щоб ознайомитись з доступними збірниками, зверніться до цієї статті.

2. Налаштування спеціальних збігів

Щоб отримати Hamcrest, нам потрібно додати наступну залежність Maven до нашого pom.xml :

 org.hamcrest java-hamcrest 2.0.0.0 test 

Останню версію Hamcrest можна знайти на Maven Central.

3. Представляємо TypeSafeMatcher

Перш ніж починати з наших прикладів, важливо зрозуміти клас TypeSafeMatcher . Нам доведеться розширити цей клас, щоб створити власний збіг.

TypeSafeMatcher - це абстрактний клас, тому всі підкласи повинні реалізовувати такі методи:

  • matchSafely (T t) : містить нашу логіку відповідності
  • descriTo (Опис опису) : налаштовує повідомлення, яке отримає клієнт, коли наша логічна відповідність не виконана

Як ми можемо бачити в першому методі, TypeSafeMatcher параметризований, тому нам доведеться оголосити тип, коли ми його використовуємо. Це буде тип об’єкта, який ми тестуємо.

Давайте зрозуміємо це, розглянувши наш перший приклад у наступному розділі.

4. Створення onlyDigits Шукача

Для нашого першого випадку використання ми створимо збіг, який повертає true, якщо певний рядок містить лише цифри.

Отже, onlyDigits, застосовані до “123”, повинні повертати true, тоді як “ hello1 ” та “ bye ” повинні повертати false.

Давайте розпочнемо!

4.1. Створення матчів

Для початку ми створимо клас, який розширює TypeSafeMatcher :

public class IsOnlyDigits extends TypeSafeMatcher { @Override protected boolean matchesSafely(String s) { // ... } @Override public void describeTo(Description description) { // ... } }

Зверніть увагу, оскільки об’єктом, який ми тестуємо, є текст, ми параметризуємо наш підклас TypeSafeMatcher за допомогою класу String.

Тепер ми готові додати нашу реалізацію:

public class IsOnlyDigits extends TypeSafeMatcher { @Override protected boolean matchesSafely(String s) { try { Integer.parseInt(s); return true; } catch (NumberFormatException nfe){ return false; } } @Override public void describeTo(Description description) { description.appendText("only digits"); } }

Як ми бачимо, matchSafey намагається проаналізувати наш вхідний рядок у ціле число . Якщо це вдається, це повертає істину . Якщо він не вдається, він повертає false . Він успішно реагує на наш випадок використання.

З іншого боку, descriTo додає текст, який відображає наші очікування. Ми побачимо, як це буде показано далі, коли ми використаємо наш матч.

Нам потрібна лише одна річ для завершення нашого збігу: статичний метод доступу до нього , тому він поводиться як решта вбудованих збігів.

Отже, ми додамо щось подібне:

public static Matcher onlyDigits() { return new IsOnlyDigits(); }

І ми закінчили! Давайте подивимося, як використовувати цей збіг у наступному розділі.

4.2. Використання відповідника

Щоб використовувати наш абсолютно новий матч, ми створимо тест :

@Test public void givenAString_whenIsOnlyDigits_thenCorrect() { String digits = "1234"; assertThat(digits, onlyDigits()); }

І це все. Цей тест пройде, оскільки вхідний рядок містить лише цифри. Пам’ятайте, що, щоб зробити його трохи читабельнішим, ми можемо використовувати збіг , який діє як обгортка над будь-яким іншим збігом :

assertThat(digits, is(onlyDigits()));

Нарешті, якби ми провели той самий тест, але з входом "123ABC", вихідним повідомленням буде:

java.lang.AssertionError: Expected: only digits but: was "123ABC"

Тут ми бачимо текст , який ми додаються до describeTo методі. Як ми могли помітити, важливо створити правильний опис того, що очікується в тесті.

5. подільнийBy

Отже, що, якби ми хотіли створити відповідник, який визначає, чи число ділиться на інше число? Для цього сценарію нам доведеться десь зберігати один із параметрів.

Давайте подивимося, як ми можемо це зробити:

public class IsDivisibleBy extends TypeSafeMatcher { private Integer divider; // constructors @Override protected boolean matchesSafely(Integer dividend) { if (divider == 0) { return false; } return ((dividend % divider) == 0); } @Override public void describeTo(Description description) { description.appendText("divisible by " + divider); } public static Matcher divisibleBy(Integer divider) { return new IsDivisibleBy(divider); } }

Досить просто , ми просто додали новий атрибут до нашого класу і призначили його під час побудови . Потім ми просто передали його як параметр нашому статичному методу:

@Test public void givenAnEvenInteger_whenDivisibleByTwo_thenCorrect() { Integer ten = 10; Integer two = 2; assertThat(ten,is(divisibleBy(two))); } @Test public void givenAnOddInteger_whenNotDivisibleByTwo_thenCorrect() { Integer eleven = 11; Integer two = 2; assertThat(eleven,is(not(divisibleBy(two)))); }

І це все! Ми вже маємо наш матчер, використовуючи більше одного входу!

6. Висновок

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

Більше того, якщо якийсь конкретний випадок не висвітлюється, Hamcrest також надає підтримку для створення спеціальних збігів, які будуть використовуватися за певними сценаріями - як ми вже досліджували тут . Їх просто створити, і вони використовуються точно так само, як ті, що входять до бібліотеки.

Щоб отримати повну реалізацію цих прикладів, зверніться до проекту GitHub.