Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@Mock(serializable = true) no longer works with parameterized types #2979

Closed
cpovirk opened this issue Apr 17, 2023 · 2 comments · Fixed by #3007
Closed

@Mock(serializable = true) no longer works with parameterized types #2979

cpovirk opened this issue Apr 17, 2023 · 2 comments · Fixed by #3007

Comments

@cpovirk
Copy link
Contributor

cpovirk commented Apr 17, 2023

This appears to be a result of #2923, though I've gotten myself a little confused trying to run the Mockito tests, so I haven't 100% confirmed that.

As a demonstration, I edited MocksSerializationForAnnotationTest.java to contain:

@Mock(serializable = true)
Supplier<Object> parameterizedSupplier;

@Test
public void should_allow_mock_of_parameterized_type_to_be_serializable() throws Exception {
  serializeAndBack(parameterizedSupplier);
}

That fails with:

org.mockitousage.basicapi.MocksSerializationForAnnotationTest > should_allow_mock_of_parameterized_type_to_be_serializable FAILED
    java.io.NotSerializableException: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)
        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)
        at org.mockitoutil.SimpleSerializationUtil.serializeMock(SimpleSerializationUtil.java:40)
        at org.mockitoutil.SimpleSerializationUtil.serializeAndBack(SimpleSerializationUtil.java:21)
        at org.mockitousage.basicapi.MocksSerializationForAnnotationTest.should_allow_mock_of_parameterized_type_to_be_serializable(MocksSerializationForAnnotationTest.java:77)

I think I'm seeing it fixed if I change CreationSettings.genericTypeToMock to be transient. That might be OK: The motivation for starting to use genericTypeToMock seems to have been for disambiguating between fields for @InjectMocks, so I wouldn't expect it to be needed after deserialization. But maybe genericTypeToMock is used in more advanced ways that would matter after deserialization (say, to figure out what type a Supplier<String> should return from its get method in some cases), or maybe the hope is to use it in such ways in the future?

(Alternatively, Mockito could skip setting the generic type for serializable mocks, but that could be surprising. Or Mockito could perform its own custom serialization and deserialization of parameterized types, but that sounds like a lot of work for little payoff.)

In the meantime, we can work around the problem by using Mockito.mock(..., withSettings().serializable()) instead of @Mock(serializable = true) (since the former doesn't call genericTypeToMock(...)). But we do have one team that is reporting seeing this in a bunch of tests, so they'd have to shift their habits.

@jfrantzius again :)

@cpovirk
Copy link
Contributor Author

cpovirk commented Apr 24, 2023

(Quick update: We've successfully patched out copy of Mockito to make CreationSettings.genericTypeToMock be transient, so we're unblocked.)

@TimvdLippe
Copy link
Contributor

I think changing it to transient is okay, at least until somebody reports it breaks, but as it is already broken, I would be surprised by that. @cpovirk can you please upstream that patch with a regression test?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants