Search code examples
javaunit-testinglambdamockito

Spying a lambda with mockito


I have encountered an interesting issue while writing an unit test which involved mocking a lambda.

@Test
public void spyingLambda() {
    final Supplier<String> spy = Mockito.spy((Supplier) () -> "1");
    spy.get();
}

Running this test fails with the following error:

Mockito cannot mock/spy because : - final class

One workaround for the above issue is replacing the lambda with anonymous implementation:

@Test
public void spyingAnonymousImplementation() {
    final Supplier<String> spy = Mockito.spy(new Supplier<String>() {
        @Override
        public String get() {
            return "1";
        }
    });
    spy.get();
}

Though both tests are exactly the same (the IDE suggest even replacing the anonymous implementation with lambda), the second test doesn't fail.

I was wondering if this is a known issue which could be fixed in mockito or are there any other workarounds.


Solution

  • Another way of dealing with this issue is the following:

    /**
     * This method overcomes the issue with the original Mockito.spy when passing a lambda which fails with an error
     * saying that the passed class is final.
     */
    @SuppressWarnings("unchecked")
    static <T, P extends T> P spyLambda(Class<T> lambdaType, P lambda) {
        return (P) mock(lambdaType, delegatesTo(lambda));
    }
    

    Which allows spying the lambda by changing the first method as following:

    @Test
    void spyingLambda() {
        Supplier<String> spy = spyLambda(Supplier.class, () -> "1");
        spy.get();
    }
    

    Hopefully the above examples might help others who encounter the same issue.