1

I am trying to use a mock and check that the argument passed into the mock is the correct ArrayList<MyModel>. I have defined the boolean equals method on MyModel, but I can't find the right matcher that uses the equals method. The matchers I have been writing only compare the object_id's which are obviously different. My test looks something like so:

MainActivity activity = mock(MainActivity.class);
MyRequest subject = new MyRequest(activity);
ArrrayList<MyModel> list = ...;
subject.makeRequest();
verify(activity).handleSuccess(argThat(is(list)));

Does anyone know a matcher that will use the boolean equal on MyModel?

trev9065
  • 3,371
  • 4
  • 30
  • 45
  • Why this doesn't work for you? `verify(activity).handleSuccess(argThat(equalTo(expected)));` – aim Aug 02 '13 at 19:03
  • @aim it compares the object_id's and since the argument that is called is a different instance of `ArrayList` the equality comparison returns false. – trev9065 Aug 02 '13 at 19:55
  • 2
    Hmm.. I thought `equalTo` invoke equal on `ArrayList` and then it applies on each element of list (like this `java.util.AbstractList#equals`)... – aim Aug 02 '13 at 20:00
  • @aim I thought the same, but it is giving me the same error. – trev9065 Aug 02 '13 at 21:32
  • Check [this](https://gist.github.com/funster/6143998) out (it's not android classes but it just simple idea), if you run it prints: `Equals invoked: MyModel{id=1} Equals invoked: MyModel{id=1}`. So `equalTo` compared base on `equals` method, but not reference (or object_id's) – aim Aug 02 '13 at 22:31
  • 1
    Post the failure message for clarity. The `equalTo` matcher indeed uses the object's built-in `equals` method. Note that `ArrayList`'s method requires the elements to be in the same order in both lists. – David Harkness Aug 04 '13 at 23:39

1 Answers1

0

According to the Hamcrest tutorial, you can use any of the following to compare using Object.equals:

  • argThat(is(list))
  • argThat(is(equalTo(list))
  • argThat(equalTo(list))

Furthermore, List.equals(Object) is specifically defined to compare e1.equals(e2) for every element e1 and e2 in corresponding positions in the list.

Double-check that you've fulfilled everything you need to do to properly override equals:

  • Does your MyModel.equals method receive an Object parameter instead of a MyModel? If the parameter is any type other than Object, it isn't a proper override and won't work.
  • Is MyModel.equals reflective, symmetric, transitive, and consistent? It's unlikely that your equals would fail in the other direction, but there's no guarantee on which object the equals method will be called.
  • When two objects are equal, do their hashCode values return equal integers? Collection implementations are free to check hash code equality as a "shortcut" before checking object-to-object equality.

To check those points, you may want to write a test to specifically for equals. I recommend Guava's EqualsTester, which checks most of these properties automatically for you.

Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251