Използване на съвпадение на номера на Hamcrest

1. Общ преглед

Hamcrest предоставя статични съвпадения, за да улесни утвърждаването на единични тестове и по-четливо. Можете да започнете да проучвате някои от наличните мачове тук.

В тази статия ще се потопим по-дълбоко в съвпаденията, свързани с числата.

2. Настройка

За да получим Hamcrest, просто трябва да добавим следната зависимост на Maven към нашия pom.xml :

 org.hamcrest java-hamcrest 2.0.0.0 

Най-новата версия на Hamcrest може да бъде намерена на Maven Central.

3. Съвпадения на близост

Първият набор от съвпадения, които ще разгледаме, са тези, които проверяват дали някой елемент е близо до стойност +/- грешка .

По-официално:

value - error <= element <= value + error

Ако сравнението по-горе е вярно, твърдението ще премине.

Нека го видим в действие!

3.1. isClose с двойни стойности

Да кажем, че имаме число, съхранено в двойна променлива, наречена действително. И ние искаме да тестваме дали действителното е близо до 1 +/- 0,5.

Това е:

1 - 0.5 <= actual <= 1 + 0.5 0.5 <= actual <= 1.5

Сега нека създадем единичен тест, използвайки съвпадение isClose :

@Test public void givenADouble_whenCloseTo_thenCorrect() { double actual = 1.3; double operand = 1; double error = 0.5; assertThat(actual, closeTo(operand, error)); }

Тъй като 1.3 е между 0,5 и 1,5, тестът ще премине. По същия начин можем да тестваме негативния сценарий:

@Test public void givenADouble_whenNotCloseTo_thenCorrect() { double actual = 1.6; double operand = 1; double error = 0.5; assertThat(actual, not(closeTo(operand, error))); }

Сега, нека да разгледаме подобна ситуация с различен тип променливи.

3.2. isClose С BigDecimal Стойности

isClose е претоварен и може да се използва по същия начин, както при двойни стойности, но с BigDecimal обекти :

@Test public void givenABigDecimal_whenCloseTo_thenCorrect() { BigDecimal actual = new BigDecimal("1.0003"); BigDecimal operand = new BigDecimal("1"); BigDecimal error = new BigDecimal("0.0005"); assertThat(actual, is(closeTo(operand, error))); } @Test public void givenABigDecimal_whenNotCloseTo_thenCorrect() { BigDecimal actual = new BigDecimal("1.0006"); BigDecimal operand = new BigDecimal("1"); BigDecimal error = new BigDecimal("0.0005"); assertThat(actual, is(not(closeTo(operand, error)))); }

Моля, обърнете внимание, че функцията is matcher украсява само други съвпадения, без да добавя допълнителна логика . Просто прави цялото твърдение по-четливо.

Това е всичко за съвпаденията близост. След това ще разгледаме съвпаденията на поръчките.

4. Поръчайте съвпадения

Както се казва в името им, тези съпоставящи помагат да се твърдят по отношение на реда.

Има пет от тях:

  • сравняваEqualTo
  • по-голям от
  • largerThanOrEqualTo
  • по-малко от
  • lessThanOrEqualTo

Те са доста обясними, но нека да видим някои примери.

4.1. Поръчка кибрит С Integer V alues

Най-често срещаният сценарий би бил използването на тези съвпадения с числа .

И така, нека да продължим и да създадем няколко теста:

@Test public void given5_whenComparesEqualTo5_thenCorrect() { Integer five = 5; assertThat(five, comparesEqualTo(five)); } @Test public void given5_whenNotComparesEqualTo7_thenCorrect() { Integer seven = 7; Integer five = 5; assertThat(five, not(comparesEqualTo(seven))); } @Test public void given7_whenGreaterThan5_thenCorrect() { Integer seven = 7; Integer five = 5; assertThat(seven, is(greaterThan(five))); } @Test public void given7_whenGreaterThanOrEqualTo5_thenCorrect() { Integer seven = 7; Integer five = 5; assertThat(seven, is(greaterThanOrEqualTo(five))); } @Test public void given5_whenGreaterThanOrEqualTo5_thenCorrect() { Integer five = 5; assertThat(five, is(greaterThanOrEqualTo(five))); } @Test public void given3_whenLessThan5_thenCorrect() { Integer three = 3; Integer five = 5; assertThat(three, is(lessThan(five))); } @Test public void given3_whenLessThanOrEqualTo5_thenCorrect() { Integer three = 3; Integer five = 5; assertThat(three, is(lessThanOrEqualTo(five))); } @Test public void given5_whenLessThanOrEqualTo5_thenCorrect() { Integer five = 5; assertThat(five, is(lessThanOrEqualTo(five))); }

Има смисъл, нали? Моля, обърнете внимание колко просто е да се разбере какво твърдят предикатите.

4.2. Поръчайте съвпадения със струнни стойности

Въпреки че сравняването на числата има пълен смисъл, много пъти е полезно да се сравняват други видове елементи. Ето защо съвпаденията на поръчки могат да бъдат приложени към всеки клас, който реализира сравнимия интерфейс .

Нека да видим няколко примера със Strings:

@Test public void givenBenjamin_whenGreaterThanAmanda_thenCorrect() { String amanda = "Amanda"; String benjamin = "Benjamin"; assertThat(benjamin, is(greaterThan(amanda))); } @Test public void givenAmanda_whenLessThanBenajmin_thenCorrect() { String amanda = "Amanda"; String benjamin = "Benjamin"; assertThat(amanda, is(lessThan(benjamin))); }

String реализира азбучен ред в метода compareTo от сравнимия интерфейс.

И така, има смисъл думата „Аманда“ да идва преди думата „Бенджамин“.

4.3. Поръчайте съвпадения със стойности LocalDate

Same as with Strings, we can compare dates. Let's take a look at the same examples we created above but using LocalDate objects:

@Test public void givenToday_whenGreaterThanYesterday_thenCorrect() { LocalDate today = LocalDate.now(); LocalDate yesterday = today.minusDays(1); assertThat(today, is(greaterThan(yesterday))); } @Test public void givenToday_whenLessThanTomorrow_thenCorrect() { LocalDate today = LocalDate.now(); LocalDate tomorrow = today.plusDays(1); assertThat(today, is(lessThan(tomorrow))); }

It's very nice to see that the statement assertThat(today, is(lessThan(tomorrow))) is close to regular English.

4.4. Order Matchers With Custom Classes

So, why not create our own class and implement Comparable? That way, we can leverage order matchers to be used with custom order rules.

Let's start by creating a Person bean:

public class Person { String name; int age; // standard constructor, getters and setters }

Now, let's implement Comparable:

public class Person implements Comparable { // ... @Override public int compareTo(Person o) { if (this.age == o.getAge()) return 0; if (this.age > o.getAge()) return 1; else return -1; } }

Нашата compareTo изпълнение сравнява двама души от тяхната възраст. Нека сега създадем няколко нови теста:

@Test public void givenAmanda_whenOlderThanBenjamin_thenCorrect() { Person amanda = new Person("Amanda", 20); Person benjamin = new Person("Benjamin", 18); assertThat(amanda, is(greaterThan(benjamin))); } @Test public void givenBenjamin_whenYoungerThanAmanda_thenCorrect() { Person amanda = new Person("Amanda", 20); Person benjamin = new Person("Benjamin", 18); assertThat(benjamin, is(lessThan(amanda))); }

Кибрит сега ще работят въз основа на нашите compareTo логика.

5. NaN Matcher

Hamcrest предоставя едно допълнително съвпадение на номера, за да определи дали действително е число, а не число :

@Test public void givenNaN_whenIsNotANumber_thenCorrect() { double zero = 0d; assertThat(zero / zero, is(notANumber())); }

6. Заключения

Както можете да видите, съвпаденията на числата са много полезни за опростяване на често срещаните твърдения .

Нещо повече, съвпаденията на Hamcrest като цяло са очевидни и лесни за четене .

Всичко това, плюс възможността да комбинирате съвпадения с персонализирана логика за сравнение, ги правят мощен инструмент за повечето проекти там.

Пълното изпълнение на примерите от тази статия може да бъде намерено в GitHub.