Testing in Hamcrest, which contains only one item in a list with a specific property

Using Hamcrest, we can easily check if at least one element in the list exists with a specific property, for example

List<Pojo> myList = .... MatcherAssert.assertThat(myList, Matchers.hasItem(Matchers.<Pojo>hasProperty("fieldName", Matchers.equalTo("A funny string"))))); 

where the Pojo class looks something like this:

 public class Pojo{ private String fieldName; } 

This is good, but how can I verify that there is only one object with specific properties in the list?

+6
source share
3 answers

You may need to write your own assistant. (I prefer the approval of the festival and Mockito, but used to use Hamcrest ...)

For instance...

 import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.core.IsCollectionContaining; public final class CustomMatchers { public static <T> Matcher<Iterable<? super T>> exactlyNItems(final int n, Matcher<? super T> elementMatcher) { return new IsCollectionContaining<T>(elementMatcher) { @Override protected boolean matchesSafely(Iterable<? super T> collection, Description mismatchDescription) { int count = 0; boolean isPastFirst = false; for (Object item : collection) { if (elementMatcher.matches(item)) { count++; } if (isPastFirst) { mismatchDescription.appendText(", "); } elementMatcher.describeMismatch(item, mismatchDescription); isPastFirst = true; } if (count != n) { mismatchDescription.appendText(". Expected exactly " + n + " but got " + count); } return count == n; } }; } } 

Now you can do ...

  List<TestClass> list = Arrays.asList(new TestClass("Hello"), new TestClass("World"), new TestClass("Hello")); assertThat(list, CustomMatchers.exactlyNItems(2, hasProperty("s", equalTo("Hello")))); 

An example of an exit with an error when the list ...

  List<TestClass> list = Arrays.asList(new TestClass("Hello"), new TestClass("World")); 

... will be...

 Exception in thread "main" java.lang.AssertionError: Expected: a collection containing hasProperty("s", "Hello") but: , property 's' was "World". Expected exactly 2 but got 1 

(You might want to tweak it a bit)

By the way, "TestClass" ...

 public static class TestClass { String s; public TestClass(String s) { this.s = s; } public String getS() { return s; } } 
+5
source

Matchers.hasItems specifically checks to see if the elements that you provide in the collection exist, what you are looking for is Matchers.contains , which ensures that the 2 collections are essentially the same - or in your case equivalent according to the provided

+2
source

You can also use Predicate<Pojo> and filter :

 Predicate<Pojo> predicate = pojo -> pojo.getField().equals("funny string"); long nrOfElementsSatisfyingPredicate = myList.stream() .filter(predicate::test) .count(); assertEquals(1, nrOfElementsSatisfyingPredicate); 
0
source

Source: https://habr.com/ru/post/985073/


All Articles