1

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.

4
  • Anything conceptually wrong with adding an equals implementation to your A class? Seems like a best practice IMHO. Commented May 5, 2019 at 7:04
  • I agree but this class is given , and already used heavily, changing it will require a lot of other testing although theoretically this will have no impact on other code Commented May 5, 2019 at 7:08
  • i will do it if there is no other option , but if possible would like to avoid it Commented May 5, 2019 at 7:08
  • Go to the EasyMock docs, and look at the chapter Flexible Expectations with Argument Matchers; you can match your A class based on some other property (assuming it has any). Commented May 5, 2019 at 7:59

2 Answers 2

1

You need another matcher. By default, EasyMock will indeed match using equals. But you can't do that. Your basic choices are:

  1. You don't care about matching precisely

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"); 
  1. Use a comparator

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.

  1. To have a simplified version, you can use your own matcher

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; } 
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.