Question

The EasyMock documentation is pretty clear that

The behavior for the three object methods equals(), hashCode() and toString() cannot be changed for Mock Objects created with EasyMock, even if they are part of the interface for which the Mock Object is created.

The code that I'm trying to test uses equals() to compare my mock object to something else. I'd like to do something like

expect(mock.equals(obj)).andReturn(false);

When I do that, I get an IllegalStateException. No surprise there, given what the documentation says.

Does anyone have any suggestions for an alternate approach? Is there another way to control what the mock object will return when equals() is called on it? I suppose that I can create a subclass that overrides equals()

class FooImplOverrideEquals extends FooImpl {
    public boolean equals;
    public boolean equals(Object obj) { return equals; }
}
FooImplOverrideEquals mock = createMock(FooImplOverrideEquals.class);
mock.equals = false; // instead of expect(mock.equals(obj)).andReturn(false);

but this seems inelegant. I feel like I'm missing something important (like the reason why EasyMock doesn't let you override those object methods). Is there a better solution?

Was it helpful?

Solution

Many of the mocking libraries don't support this because it's generally a bad idea. If you're doing an equals() comparison then you have a value object, not a real collaborator and you're better off using a real instance. If you're using equals() to represent some other concept (isBestFriendsWith(other)), then you can stub that if appropriate.

OTHER TIPS

You cannot change the behaviour of equals, but you can use a Comparator to implement custom or partial comparisons.

Then you can use the comparator in EasyMock expectation using the method:

EasyMock.cmp

For instance, if you have a class Person with a name and an age instance variables, and you are interested only in comparing the name:

public class Person {
    String name;
    int age;

public boolean equals(Object obj) {
        // the equals method compares the name and the age, but we are interested only in                  
        // comparing the name
        // other not-null checks...
        Person other = (Person) obj;
        if (this.age != other.age) {
            return false;
        }
        if (other.name != null) {
            return false;
        }
        return true;
    }
}

public class PersonComparator implements Comparator<Person> {
        @Override
        public int compare(Person person1, Person person2) {
            //compare only the name
            if (person1.getName().equals(person2.getName())) {
                return 0;
            }
            return -1;
        }

}

And use EasyMock.expect this way:

PersonComparator nameComparator = new PersonComparator();

Person person = new Person("Ana"); //the age doesn't matter

Person expectedPerson = EasyMock.cmp(comparisonPerson, nameComparator, LogicalOperator.EQUAL);

EasyMock.expect(personService.authenticate(expectedPerson)).andReturn(true);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top