Repository: mockito/mockito
Issue: feature request: spying on lambdas

Here's some Java8 code that works today (even with Mockito 1.x):

```
Function<Integer, Integer> incrementer = x -> x + 1;
Function<Integer, Integer> spyIncrementer = 
    mock(Function.class, AdditionalAnswers.delegatesTo(incrementer));
```

I then use `spyIncrementer` as an argument to the code that I really want to test and write a series of `verify` calls to check how `spyIncrementer` was used. In particular, I'm testing a memoization system that should only ever call call this lambda once with any given argument, so there are a series of Mockito calls along the lines of `verify(spyIncrementer, atMost(1)).apply(1);`

It would be preferable to be able to write something more like:
```
Function<Integer, Integer> spyIncrementer = spy(x -> x + 1);
```

With `org.mockito:mockito-inline:2.7.22`, this yields a `NoClassDefFoundError`. If you instead use `org.mockito:mockito-core:2.7.22`, you get _Mockito cannot mock/spy because : - final class_.

Issue comments:
Given that @brachi-wernick opened a PR for this and it appears that we never commented on this issue: I don't think we should allow this. You should use the real Function in all cases, as a spy of the function would just delegate to the actual function.

Therefore I am inclined to close this issue and corresponding PR. @mockito/core any opinion on this one?
@TimvdLippe just let me know for next time. Should i solve issues  only after you commented on them?
Yes please. Sorry for not getting to this issue sooner. We should have commented :cry: Your help is still appreciated though, so feel free to sent more PRs! Issues tagged with "Please contribute" are definitely open for community PRs: https://github.com/mockito/mockito/issues?q=is%3Aissue+is%3Aopen+label%3A%22please+contribute%22
Closing per https://github.com/mockito/mockito/issues/1068#issuecomment-446266057
@TimvdLippe sorry for commenting on a closed issue, but can you reconsider reopening it? We might have missed the point of spying on a lambda. I don't think the idea would be to stub the methods or something like that, but to verify their recorded information. For instance, this becomes extremely useful when we want to test callbacks, and we only care if the lambda was called, how many times, which arguments, etc.

Similar libraries in other languages have this feature since verifying is the most useful part of a `spy()`. A good example is [Sinon.JS](https://sinonjs.org), in which we even find an example of this usage in the documentation: https://sinonjs.org/releases/v13/spies/

I found myself in this same situation while improving some tests on a library of my authoring called [Maybe](https://github.com/JoseLion/maybe). Here's the gist of the use case 🙂 
```java
@Test void runs_the_effect_callback() {
  final Consumer<IOException> effectSpy = spy(error -> { });

  Maybe.fromSupplier(throwingOp).doOnError(IOException.class, effectSpy);

  verify(effectSpy, times(1)).accept(FAIL_EXCEPTION);
}
```

As you can see, the test only cares to verify if the `effect` callback was invoked once with the specific argument. I think there's no other way of doing this with Mockito, and since spying to the lambda will fail, I'm using @danwallach's workaround for now.  

I hope you find this helpful in improving Mockito 🙂 

Cheers!

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/Mockito.java b/src/main/java/org/mockito/Mockito.java
index e2a0ade374..24ee6da878 100644
--- a/src/main/java/org/mockito/Mockito.java
+++ b/src/main/java/org/mockito/Mockito.java
@@ -1805,6 +1805,34 @@ public static <T> T mock(Class<T> classToMock) {
         return mock(classToMock, withSettings());
     }
 
+    /**
+     *
+     * @param function a lambda expression
+     * @param <T> the lambda argument type
+     * @param <R> the lambda result type
+     * @return mock object for that lambda
+     * The following test will succeed
+     * </code></pre>
+     *  &#064;Test
+     *     public  void mockLambda(){
+     *         Function<Integer,Integer> mock = Mockito.mock(x -> x + 1);
+     *         assertEquals(2,foo(mock,1).intValue());
+     *     }
+     *
+     *     public Integer foo(Function<Integer, Integer> func, Integer arg) {
+     *         return func.apply(arg);
+     *     }
+     * </code></pre>
+     */
+    public static <T, R> java.util.function.Function<T,R> mock(java.util.function.Function<T,R> function){
+        java.util.function.Function<T,R> mock = Mockito.mock(java.util.function.Function.class);
+                when(mock.apply(any())).thenAnswer(invocation -> {
+                    T arg = invocation.getArgument(0);
+                    return function.apply(arg);
+                });
+      return mock;
+    }
+
     /**
      * Specifies mock name. Naming mocks can be helpful for debugging - the name is used in all verification errors.
      * <p>


Test patch:
diff --git a/src/test/java/org/mockito/MockitoTest.java b/src/test/java/org/mockito/MockitoTest.java
index ca8c4d4342..7253ba1c43 100644
--- a/src/test/java/org/mockito/MockitoTest.java
+++ b/src/test/java/org/mockito/MockitoTest.java
@@ -6,10 +6,13 @@
 package org.mockito;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.times;
 import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
 
 import java.util.List;
+import java.util.function.Function;
+
 import org.junit.Test;
 import org.mockito.exceptions.misusing.NotAMockException;
 import org.mockito.internal.creation.MockSettingsImpl;
@@ -62,4 +65,13 @@ public void shouldStartingMockSettingsContainDefaultBehavior() {
         assertThat(Mockito.RETURNS_DEFAULTS).isEqualTo(settings.getDefaultAnswer());
     }
 
+    @Test
+    public  void mockLambda(){
+        Function<Integer,Integer> mock = Mockito.mock(x -> x + 1);
+        assertEquals(2,foo(mock,1).intValue());
+    }
+
+    public Integer foo(Function<Integer, Integer> func, Integer arg) {
+        return func.apply(arg);
+    }
 }