martin
martin

Reputation: 2194

Mock void methods, which change their argument

I have an interface, which looks something like this

public interface ParameterProvider
{
    void provideParameter(Map<String, String> parameters);
}

An instance of it is used in the method I want to write a unit test for:

@Override
public void process(...)
{
    ...
    Map<String, String> parameters = new HashMap<String, String>();
    parameterProvider.provideParameter(parameters);
    ...
}

How can I mock the ParameterProvider to perform actions on the argument, that's passed to its provideParameter-method?

My first idea was to change the return type from void to Mapand actually return the modified Map (which seems a lot nicer anyway). Then testing is no problem:

when(parameterProvider.provideParameter(anyMap())).thenReturn(MY_PARAMETERS);

However since the interface is used in a framework, which for some odd reason seems to require the methods to be void, this is not an option right now.

Is there a way to still mock this thing. I'm using Mockito, but I don't need to stick with it, if there are other mocking frameworks to get the job done.

EDIT: I also tried to use doAnwser, but I don't see how to modify the argument passed to the method:

doAnswer(new Answer() {
    public Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        args[0] // that's the argument I want to modify
        return null;
    }})
.when(parameterProvider).provideParameter(anyMap());

Upvotes: 11

Views: 10337

Answers (1)

Brian Agnew
Brian Agnew

Reputation: 272247

Mockito.doAnswer() will allow you to mock void methods and manipulate the parameters passed to it via your own closure/class implementing Answer (provided your parameters are mutable, obviously).

So given your code:

doAnswer(new Answer() {
    public Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        args[0] // that's the argument I want to modify
        return null;
    }})
 .when(parameterProvider).provideParameter(anyMap());

args[0] would be a Map (inspect via a debugger) and assuming it's mutable, you should be able to populate/change it within your anonymous class e.g.

((Map)args[0]).put(x, y);

Upvotes: 16

Related Questions