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

Spy doesn't forward hashcode/equals to actual object #2331

Open
5 tasks done
cdalexndr opened this issue Jun 16, 2021 · 7 comments
Open
5 tasks done

Spy doesn't forward hashcode/equals to actual object #2331

cdalexndr opened this issue Jun 16, 2021 · 7 comments

Comments

@cdalexndr
Copy link

cdalexndr commented Jun 16, 2021

Mockito 3.11.1

public class MockitoTest {

    private static class ValueHolder {
        private final String value;

        public ValueHolder( String value ) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        @Override public boolean equals( Object o ) {
            if (this == o) return true;
            if (!(o instanceof ValueHolder)) return false;
            ValueHolder that = (ValueHolder) o;
            return getValue().equals( that.getValue() );
        }

        @Override
        public int hashCode() {
            return Objects.hash( getValue() );
        }
    }

    @Test
    public void test() {
        ValueHolder value = new ValueHolder( "test" );
        ValueHolder spy = Mockito.spy( value );
        assert value.equals( spy );
        assert spy.equals( value ); //fails
        assert value.hashCode() == spy.hashCode(); //fails
    }
}
  • The mockito message in the stacktrace have useful information, but it didn't help
  • The problematic code (if that's possible) is copied here;
    Note that some configuration are impossible to mock via Mockito
  • Provide versions (mockito / jdk / os / any other relevant information)
  • Provide a Short, Self Contained, Correct (Compilable), Example of the issue
    (same as any question on stackoverflow.com)
  • Read the contributing guide
@saurabh7248
Copy link
Contributor

To create a mock a subclass of a mock is created through SubclassBytecodeGenerator.mockClass() here we can see that hashCode method is intercepted and handled by MockMethodInterceptor.ForHashCode. Here the code returns System.identityHashCode(thiz) as the hashcode where thiz is the object returned by Mockito.spy(). Same is the case of equals, where this==that is returned when equals is called.

@TimvdLippe shoud we add handling to delegate the call to hashCode and equals of spied object ?

@TimvdLippe
Copy link
Contributor

Hm, I guess we could? I wonder if any tests start failing after that, but if they all pass I am okay with making that change yeah 👍

saurabh7248 pushed a commit to saurabh7248/mockito that referenced this issue Jul 30, 2021
Has conditionally on basis of whether default answer is pass to actual methods made hash code and equals pass to actual methods.
saurabh7248 pushed a commit to saurabh7248/mockito that referenced this issue Jul 30, 2021
Has conditionally on basis of whether default answer is pass to actual methods made hash code and equals pass to actual methods.
Intellij seems to had only pushed import and not the test
@saurabh7248
Copy link
Contributor

I have opened a pull request here.
@TimvdLippe could you please review it.

marcbaechinger pushed a commit to google/ExoPlayer that referenced this issue Aug 20, 2021
After the fix in mockito/mockito#2331, the calls to
equals on the fake transfer listener (due to its use in a list of listeners)
are treated as interactions with it, meaning that the current verification of
'no more interactions' will fail.

This change makes the transfer listener used for testing count bytes then
delegate to another (mock) transfer listener that's passed in to avoid the
problem.

PiperOrigin-RevId: 391949619
marcbaechinger pushed a commit to google/ExoPlayer that referenced this issue Aug 27, 2021
*** Original commit ***

Avoid adding spy to list in DataSourceContractTests

After the fix in mockito/mockito#2331, the calls to
equals on the fake transfer listener (due to its use in a list of listeners)
are treated as interactions with it, meaning that the current verification of
'no more interactions' will fail.

This change makes the transfer listener used for testing count bytes then
delegate to another (mock) transfer listener that's passed in to avoid the
problem.

***

PiperOrigin-RevId: 393093785
@cdalexndr
Copy link
Author

cdalexndr commented Sep 11, 2021

This issue needs to be reopened because it still reproduces with v3.12.4

Was fixed in v3.12.0 by 123beb8, but 1a8946f reverted the fix.
e1f9855 also removed the test added by initial fix.

@cdalexndr
Copy link
Author

cdalexndr commented Mar 5, 2022

@raphw why was 1a8946f needed? (Note that the type cache was fixed 2h before your commit: 4f81d4f)

cdalexndr added a commit to cdalexndr/mockito that referenced this issue Mar 5, 2022
@raphw
Copy link
Member

raphw commented Mar 5, 2022

We use the same generated classes for both spy and mock classes. This is why we had to unify the behaviour. Internally, a spy is nothing but a mock with a prefefined delegatory answer. This is why a spy needs to behave like a mock.

Generally, I agree with that this behaviour would to be preferred. But it would require a lot of internal refactoring as we often rely on the hashcode/equals properties of mocks.

@dominiktopp
Copy link

dominiktopp commented Mar 1, 2024

Stumbled upon this today.

If this cannot be fixed in the near future I would suggest to at least document this e.g. in de JavaDoc of @Spy annotation and Mockito.spy method.

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.

5 participants