Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using mockito; is it possible to mock a method that takes a lambda as a parameter and assert variables captured by the lambda?

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.

like image 277
GavPay360 Avatar asked May 18 '16 11:05

GavPay360


People also ask

What can be mocked with Mockito?

We can use Mockito class mock() method to create a mock object of a given class or interface. This is the simplest way to mock an object. We are using JUnit 5 to write test cases in conjunction with Mockito to mock objects.

Does Mockito mock call real method?

Mockito allows us to partially mock an object. This means that we can create a mock object and still be able to call a real method on it. To call a real method on a mocked object we use Mockito's thenCallRealMethod().

Can you mock a variable?

If you need to mock a global variable for all of your tests, you can use the setupFiles in your Jest config and point it to a file that mocks the necessary variables. This way, you will have the global variable mocked globally for all test suites.

How do mocks work Mockito?

With Mockito, you create a mock, tell Mockito what to do when specific methods are called on it, and then use the mock instance in your test instead of the real thing. After the test, you can query the mock to see what specific methods were called or check the side effects in the form of changed state.


1 Answers

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();
like image 186
Nicolas Filotto Avatar answered Oct 27 '22 02:10

Nicolas Filotto