Repository: mockito/mockito
Issue: Serializable flag doesn't make mock serializable

I have a simple example test like this (I'm using junit5 with mockito-junit-jupiter extension)

```
@ExtendWith(MockitoExtension.class)
class ExampleTest {
  @Mock(serializable = true) private Iterable<?> it;

  @Test
  void shouldSerializeAndDeserializeIt() throws IOException, ClassNotFoundException {
    // when
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    new ObjectOutputStream(out).writeObject(it);
    ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
    Iterable<?> deserializedIt = (Iterable<?>) new ObjectInputStream(in).readObject();

    // then
    assertThat(deserializedIt).isEqualToComparingFieldByFieldRecursively(it);
  }
}
```

And I'm getting this error on during instance serialization:

```
java.io.NotSerializableException: org.mockito.internal.junit.DefaultStubbingLookupListener
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)
	at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
	at java.base/java.util.ArrayList.writeObject(ArrayList.java:896)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at java.base/java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1130)
	at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1497)
	at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
	at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
	at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
	at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
	at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
	at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
	at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
	at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
	at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
	at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
	at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
	at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
	at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
	at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
	at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
	at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
	at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
	at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
	at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
	at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
``` 



Issue comments:
We have observed similar things before. It seems like a mock is something keeping a hard reference to a listener. @TimvdLippe Do you remember me mentioning to having observed this some times? Were you working with the listener parts originally?
Yes I recall that discussion. The listener parts were introduced by @mockitoguy. I have run into this problem myself from time to time and have not figured out where it goes wrong. These listeners should not even be considered when serializing mocks.

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/internal/junit/DefaultStubbingLookupListener.java b/src/main/java/org/mockito/internal/junit/DefaultStubbingLookupListener.java
index 21212a6754..b6a80c64a3 100644
--- a/src/main/java/org/mockito/internal/junit/DefaultStubbingLookupListener.java
+++ b/src/main/java/org/mockito/internal/junit/DefaultStubbingLookupListener.java
@@ -12,6 +12,7 @@
 import org.mockito.quality.Strictness;
 import org.mockito.stubbing.Stubbing;
 
+import java.io.Serializable;
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
@@ -22,7 +23,9 @@
  * Default implementation of stubbing lookup listener.
  * Fails early if stub called with unexpected arguments, but only if current strictness is set to STRICT_STUBS.
  */
-class DefaultStubbingLookupListener implements StubbingLookupListener {
+class DefaultStubbingLookupListener implements StubbingLookupListener, Serializable {
+
+    private static final long serialVersionUID = -6789800638070123629L;
 
     private Strictness currentStrictness;
     private boolean mismatchesReported;


Test patch:
diff --git a/src/test/java/org/mockitousage/serialization/StrictStubsSerializableTest.java b/src/test/java/org/mockitousage/serialization/StrictStubsSerializableTest.java
new file mode 100644
index 0000000000..9d786695fc
--- /dev/null
+++ b/src/test/java/org/mockitousage/serialization/StrictStubsSerializableTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.serialization;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.io.Serializable;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+import static org.mockitoutil.SimpleSerializationUtil.serializeAndBack;
+
+@RunWith(MockitoJUnitRunner.StrictStubs.class)
+public class StrictStubsSerializableTest {
+
+    @Mock(serializable = true) private SampleClass sampleClass;
+
+    @Test
+    public void should_serialize_and_deserialize_mock_created_with_serializable_and_strict_stubs() throws Exception {
+        // given
+        when(sampleClass.isFalse()).thenReturn(true);
+
+        // when
+        SampleClass deserializedSample = serializeAndBack(sampleClass);
+        // to satisfy strict stubbing
+        deserializedSample.isFalse();
+        verify(deserializedSample).isFalse();
+        verify(sampleClass, never()).isFalse();
+
+        // then
+        assertThat(deserializedSample.isFalse()).isEqualTo(true);
+        assertThat(sampleClass.isFalse()).isEqualTo(true);
+    }
+
+    static class SampleClass implements Serializable {
+
+        boolean isFalse() {
+            return false;
+        }
+    }
+}