Using mockito; is it possible to mock a method tha

2019-06-26 18:01发布

问题:

I have a method that looks that looks something like:

public Response methodA(ParamObject po, Supplier<Response> supplier)

the Supplier contains a call to a method on another class.

I am attempting to wrap some code in the Supplier in a more complex set of logic, something akin to a Strategy pattern, it does make the code easier to follow.

It looks something like:

public Controller {    
   private Helper helper;
   private Delegate delegate;

   public void doSomething() {
     ParamObject po = ....
     delegate.methodA(po, () -> {
         helper.doSomethingElse(v1, v2);
     }
   }

}

In my test for Controller I have mocked both Helper and Delegate, I wish to validate that helper.doSomething is called with the correct parameter values, and then return a mocked response.

Given that delegate is a mock, the Supplier is never actually executed, so no verification of the calls to helper can be mocked or verified.

Is it possible to do this? It feels like I should be able to tell mockito to capture the lambda, and or the variables the lambda itself captured and assert they are the right values return my mock response if they are the values I was looking for.

回答1:

Assuming that your class Helper looks like this:

public class Helper {
    public Response doSomethingElse(String v1, String v2) {
        // rest of the method here
    }
}

Then it could be done like this:

Helper helper = mock(Helper.class);
// a and b are the expected parameters
when(helper.doSomethingElse("a", "b")).thenReturn(new Response());
// a and c are not the expected parameters
when(helper.doSomethingElse("a", "c")).thenThrow(new AssertionError());

Delegate delegate = mock(Delegate.class);
// Whatever the parameters provided, simply execute the supplier to 
// get the response to provide and to get an AssertionError if the
// parameters are not the expected ones
when(delegate.methodA(any(), any())).then(
    new Answer<Response>() {
        @Override
        public Response answer(final InvocationOnMock invocationOnMock) throws Throwable {
            return ((Supplier<Response>) invocationOnMock.getArguments()[1]).get();
        }
    }
);

Controller controller = new Controller();
controller.helper = helper;
controller.delegate = delegate;
controller.doSomething();