Reputation: 185
I would like to unit test a method with multiple internal calls to a class I want to mock using EasyMock
.
The test method actually runs 5 times and calls the mocked method.
During each loop, I will create some objects, all of the same class (let's say of class A). The private method will call the mock object method that takes the instance of class A, evaluate it and return a result.
In the end, the public method will return a List of results.
I tried the standard EasyMock.expect(MockClass.method(A)).andReturn()
but it does not work since there is no implementation of equals()
for class A
:
// this is the method example I am trying to test
public methodToTest(){
// some logic
privateMethodToTest(x);
// some logic
}
private List<B> privateMethodToTest(int x){
List<B> list = new ArrayList<>();
List<A> all = getObjects(x); //getObjects private method
for (A a:all){
list.add(objectToMock.methodToMock(a));
return list;
}
This is how I would like it to work:
EasyMock.createMock(ObjectToMock.class);
EasyMock.expect(ObjectToMock.methodToMock(A)/* when A.getValue() == 1 */.andReturn("B object number 1")
EasyMock.expect(ObjectToMock.methodToMock(A)/* when A.getValue() == 2 */.andReturn("B object number 2")
//... and so on
//object of class A does not implement equals()
I am not sure how to do it and I was not able to find any similar example or answer to my question.
Upvotes: 1
Views: 471
Reputation: 5731
You need another matcher. By default, EasyMock will indeed match using equals
. But you can't do that. Your basic choices are:
If seems to be the easiest for you. It means doing:
expect(objectToMock.methodToMock(anyObject()).andReturn("B object number 1");
expect(objectToMock.methodToMock(anyObject()).andReturn("B object number 2");
According to your comment, you might actually prefer this
expect(mock.methodToTest(EasyMock.cmp(new A(1), Comparator.comparingInt(A::getValue), LogicalOperator.EQUAL))).andReturn(1);
The only problem is that you need a A
with the correct value to compare with.
The expectation using the custom matcher right below.
expect(mock.methodToTest(cmp(0))).andReturn(3);
public static <T> T cmp(int value) {
reportMatcher(new IArgumentMatcher() {
@Override
public boolean matches(Object argument) {
return value == ((A) argument).getValue();
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("A.value=").append(value);
}
});
return null;
}
Upvotes: 1
Reputation: 15634
When unittesting we verify public observable behavior of the code under test, that is return values and communication with dependencies.
Anything else is implementation detail which we do not test. The reason is that you might want to refactor your code. That means you want to improve the structure of your code without changing its behavior. Your unittest schould verify that you did not change behavior accidentally. But they can only do this if you do not have to change them too.
Upvotes: 0