Search code examples
javajunitasserthamcrest

Using hamcrest to assert that I get a collection of Objects back and that one of them has a property set to a particular value?


I just started using Hamcrest, so I'm probably doing it all wrong.

I have a List<Foo> foos and the Foo interface looks a bit like this:

public abstract interface Foo {

  public String getBar();

}

It is implemented by impl.FooImpl:

public class FooImpl implements Foo {

  protected String _bar = "some value";

  public String getBar() {
    return _bar;
  }

}

My assert looks like this:

assertThat(
  foos, 
  Matchers.hasItem(
    Matchers.<Foo> hasProperty(
      "bar", 
      equalTo("some value")
    )
  )
);

Unfortunately, JUnit/Hamcrest isn't happy:

java.lang.AssertionError: 
Expected: a collection containing hasProperty("bar", "someValue")
     got: <[com.example.impl.FooImpl@2c78bc3b]>

Any idea what I need to do to fix this?

Update: My "test" class is here:

public class FooTest {
  public static void main(String... args) throws Exception {
    List<Foo> foos = Arrays.<Foo> asList(new FooImpl());
      assertThat(
        foos, 
        Matchers.<FooImpl> hasItem(Matchers.hasProperty("bar", equalTo("some value")))
      );
  }
}

Clearly, what I'd like to see is that assert pass without getting an exception... :)

Update: this is now fixed; I just set up a blank maven project in IntelliJ and it ran fine. It might have been down to a typo, or me importing the wrong method in Eclipse, but it's a OSI Layer 8 problem for sure. I asked for the conversation to be closed. Sorry everyone, and thanks for your help.


Solution

  • The code you posted works fine. The error you have is due to a mismatch between "someValue" and "some value" in the code you're running locally. Upgrade to Hamcrest 1.3 and you'll get a clearer error message:

    Expected: a collection containing hasProperty("bar", "someValue")
        but: property 'bar' was 'some value'
    

    Since you may be getting different results, here's a full example that passes, with JUnit 4.11 and Hamcrest 1.3. In Foo.java:

    public class Foo {
        public String getBar() {
            return "some value";
        }
    }
    

    And in FooTest.java:

    import static org.junit.Assert.assertThat;
    
    import java.util.Arrays;
    import java.util.List;
    
    import org.hamcrest.Matchers;
    import org.junit.Test;
    
    public class FooTest {
        @Test
        public void test() {
            List<Foo> foos = Arrays.asList(new Foo());
    
            assertThat(foos,
                    Matchers.<Foo>hasItem(Matchers.hasProperty("bar", Matchers.equalTo("some value"))));
        }
    }
    

    If I intentionally break this test by changing the property name in the test to "notbar" then I get:

    java.lang.AssertionError: 
    Expected: a collection containing hasProperty("notbar", "some value")
         but: No property "notbar"
    

    If, instead, I break it by expecting "some other value", then I get:

    java.lang.AssertionError: 
    Expected: a collection containing hasProperty("bar", "some other value")
         but: property 'bar' was "some value"
    

    If you're getting different, or less clear, errors, you may have a separate issue.