EasyMock: Void Methods

JavaUnit TestingMockingVoidEasymock

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

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

Solution 3 - Java

If you only want access to the parameters for later, you might also appreciate the Captures class which is new to EasyMock 2.4.

You can use an instance of the "Capture" class in place of a matcher. When your mocked method is invoked, the Capture instance will store the parameter it was invoked with.

Capture<ChartPanel> captured = new Capture<ChartPanel>();
// setChartPanel is going to be called during execution;
// we want to verify some things about the ChartPanel
// instance it's invoked with
chartMock.setChartPanel(capture(captured));
replay(chartMock);

ufdm.setChartAnnotater(chartMock);
// afterPropertiesSet triggers the setChartPanel call...
ufdm.afterPropertiesSet();
verify(chartMock);

// verify some things about the ChartPanel parameter our
// mock object was invoked with
assertSame(plot, captured.getValue().getChart().getPlot());

Solution 4 - Java

You might want to check out PowerMock. EasyMock is based on the proxy reflection API meaning everything is a proxy and you can only test interfaces, and thus only non-final methods and classes. This might work for some, but if you're testing the world as built, you'll need more power.

With PowerMock the Java 5 instrumentation API removes the limitations. No need to write mock object implementations of the object to be tested (just ugly IMO). Couple PowerMock with Mockito (or JMockit) and you'll really be off to the races.

Of course, there is the other direction of rewriting your code to be more easily tested, which is generally a good idea too, if possible.

Solution 5 - Java

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIker JimenezView Question on Stackoverflow
Solution 1 - Javamatt bView Answer on Stackoverflow
Solution 2 - JavaEdward Q. BridgesView Answer on Stackoverflow
Solution 3 - JavapieperaView Answer on Stackoverflow
Solution 4 - JavaJoseph LustView Answer on Stackoverflow
Solution 5 - JavaMarc WView Answer on Stackoverflow