Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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());
like image 811
martin Avatar asked Feb 05 '15 10:02

martin


People also ask

How do you Mock a void method in Java?

Void method is mostly mocked to check if it is called with correct parameters. For mocking void method when-then mechanism of mockito does not work because it needs return value. Void methods can be handled using doNothing (), doAnswer (), doThrow () or doCallRealMethod () doNothing () : Completely ignore the void method.

Why when () method of Mockito does not work with void method?

Because, when () method of mockito works with return value and does not work when method is void. How to mock void method in mockito? In Mockito we can use different methods to call real method or mock void method. We can use one of the options as per requirements doNothing () : Completely ignore the calling of void method, this is default behavior

What is the default behavior of Mockito's whenaddcalledverified () method?

However, doNothing () is Mockito's default behavior for void methods. This version of whenAddCalledVerified () accomplishes the same thing as the one above: DoThrow () generates an exception: We'll cover doAnswer () below.

What is donothing () method in mocking?

doAnswer () : Perform some run time or complex operations when void method is called If we just want to completely ignore the void method call, we can use doNothing (). In mocking, for every method of mocked object doNothing is the default behavior.


1 Answers

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);
like image 191
Brian Agnew Avatar answered Oct 07 '22 21:10

Brian Agnew