Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing in Hamcrest that exists only one item in a list with a specific property

With Hamcrest we can easily test that exists at least one item in a list with a specific property, e.g.

List<Pojo> myList = ....

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

where the class Pojo is something like:

public class Pojo{
  private String fieldName;
}

That's nice, but how can I check that there is exactly one object in the list with the specificed properties?

like image 320
JeanValjean Avatar asked Apr 13 '15 15:04

JeanValjean


People also ask

What is the hamcrest matcher to test if a string contains another string?

Class StringContains. Tests if the argument is a string that contains a substring. Creates a matcher that matches if the examined String contains the specified String anywhere.

Is assertThat actual is Equalto expected ))) a valid hamcrest assert statement?

assertEquals() is the method of Assert class in JUnit, assertThat() belongs to Matchers class of Hamcrest. Both methods assert the same thing; however, hamcrest matcher is more human-readable. As you see, it is like an English sentence “Assert that actual is equal to the expected value”.

Which of the following matchers method is used to test the size of a list in a test condition in JUnit?

jUnit testing using hamcrest matcher - how to test the size of a collection.

Why we use TestNG instead of hamcrest?

Hamcrest vs TestNG TestNG is a testing framework, and as noted above, Hamcrest is a matcher framework. Both frameworks allow us to make assertions; it is here where Hamcrest does a better job than TestNG. TestNG is a testing framework, and as noted above, Hamcrest is a matcher framework.


2 Answers

You might have to write your own matcher for this. (I prefer the fest assertions and Mockito, but used to use Hamcrest...)

For example...

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;
            }
        };
    }
}

You can now do...

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

    assertThat(list, CustomMatchers.exactlyNItems(2, hasProperty("s", equalTo("Hello"))));

Example fail output when the list is...

    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 customise this a bit)

By the way, "TestClass" is...

public static class TestClass {
    String s;

    public TestClass(String s) {
        this.s = s;
    }

    public String getS() {
        return s;
    }
}
like image 54
BretC Avatar answered Oct 20 '22 08:10

BretC


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

like image 22
tddmonkey Avatar answered Oct 20 '22 09:10

tddmonkey