Search code examples
javalistcomparatorhamcrest

containsInAnyOrder hamcrest matcher with custom comparator


I have a DTO class

class MyDto {
   private String f1;
   private String f2; 
   private String f3;
   // constructor
   // get set equals/hashCode
}

It has equal/hascode pair which takes into account all 3 fields.

Please take a look on test

...
var actualList = service.getActualList(...)
assertThat(actualList, containsInAnyOrder(new MyDto("a1","","c1"), new MyDto("a2","","c2")) )
...

It fails because f2 is generated on database side(so I can't predict value for that field).

I want to pass custom comparator to make test specific comparison. Is it possible to achieve it in Hamcrest ?

P.S. I don't want to rewrite equals/hashcode beause it will not be correct from my business logic standpoint


Solution

  • You can use containsInAnyOrder(Matcher...) and pass a vararg list of Matcher instances instead of a list of MyDto. You may be able to find a suitable Matcher from the Hamcrest library, such as perhaps HasPropertyWithValue or something similar. Otherwise, write your own class implementing Matcher:

    class MyMatcher implements Matcher<MyDto> {
        private final MyDto expected;
    
        public MyMatcher(MyDto expected) { this.actual = expected; }
    
        @Override
        public boolean matches(MyDto actual) {
            return actual.abc = expected.abc && actual.xyz = expected.xyz;
        }
    }
    ...
    assertThat(actualList, containsInAnyOrder(MyMatcher(new MyDto(...)),...));