EasyMock: Void Methods

Viewed 101357

I have a method that returns void in a class that is a dependency of the class I want to test.

This class is huge and I'm only using this single method from it. I need to replace the implementation of this method for the test as I want it to do something different and I need to be able to access the parameters this method receives.

I cannot find a way of doing this in EasyMock. I think I know how to do it with Mockito by using doAnswer but I don't want to add another library unless absolutely necessary.

5 Answers

If I understand what you want to do correctly, you should be able to use andAnswer():

mockObject.someMethod(eq(param1), eq(param2));
expectLastCall().andAnswer(new IAnswer() {
    public Object answer() {
        //supply your mock implementation here...
        SomeClass arg1 = (SomeClass) getCurrentArguments()[0];
        AnotherClass arg2 = (AnotherClass) getCurrentArguments()[1];
        arg1.doSomething(blah);
        //return the value to be returned by the method (null for void)
        return null;
    }
});

The EasyMock User Guide explains:

Creating Return Values or Exceptions

Sometimes we would like our mock object to return a value or throw an exception that is created at the time of the actual call. Since EasyMock 2.2, the object returned by expectLastCall() and expect(T value) provides the method andAnswer(IAnswer answer) which allows [you] to specify an implementation of the interface IAnswer that is used to create the return value or exception.

Inside an IAnswer callback, the arguments passed to the mock call are available via EasyMock.getCurrentArguments(). If you use these, refactorings like reordering parameters may break your tests. You have been warned.

If you just call the void method for each time you're expecting it to be invoked and then invoke EasyMock.expectLastCall() prior to calling replay(), Easymock will “remember” each invocation.

So I don’t think you need to explicitly call expect() (other than lastCall) since you’re not expecting anything from a void method, except its invocation.

Thanks Chris!

“Fun With EasyMock” by fellow StackOverflow user Burt Beckwith is a good blog post that provides more detail. Notable excerpt:

Basically the flow that I tend to use is:

  1. Create a mock
  2. call expect(mock.[method call]).andReturn([result]) for each expected call
  3. call mock.[method call], then EasyMock.expectLastCall() for each expected void call
  4. call replay(mock) to switch from “record” mode to “playback” mode
  5. inject the mock as needed
  6. call the test method
  7. call verify(mock) to assure that all expected calls happened

In situations like these I've found that making a nested class in my unit test class and overriding the methods with special requirements in that way is the best route. So if you're testing ClassA which has that method with the parameters you need to access, you'd do something like:

class MockClassA extends ClassA {
    @Override
    void specialMethod(String param1, String param2) {
        // do logging or manipulation of some sort
        super.specialMethod(param1,param2); // if you need to
    }
}

In my unit testing code, I then just use this instance instead. Just treat it as if it was any other mock object. Much easier than mixing libraries, which I agree is probably not a good idea.

Related