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

Verify on Spy Interface incorrect count of actual invocation #2915

Closed
bmaggi opened this issue Feb 17, 2023 · 7 comments
Closed

Verify on Spy Interface incorrect count of actual invocation #2915

bmaggi opened this issue Feb 17, 2023 · 7 comments

Comments

@bmaggi
Copy link
Contributor

bmaggi commented Feb 17, 2023

Hi,

At first, thanks for this awesome library.

During a migration from mockito 4.4.0 to mockito 5.1.1 one of my test began to fail.
It reported that the spied mock has 2 call one a method instead of one.

I figured that it has something to do with the new default mockmaker since it's working with mockito-subclass.

Still, the message is misleading : it's suggesting that there is an error while the code works as expected.
Either there is a bug in the spy count , either the message should be changed to reflect that verify/spy on interface is impossible.
(I may also have missed something :p )

Short failing example java 11/ junit 5/ mockito 5.1.1

import org.junit.jupiter.api.Test;

import static org.mockito.Mockito.*;

class MyTest {

    @Test
    void testSpyMockInterfaceMockito5() {
        MInterface spiedInterface = spy(mock(MInterface.class));
        spiedInterface.add(0);
        verify(spiedInterface).add(0);
    }
}

interface MInterface {

    void add(Integer i);
}

/*
## Mockito 5.1.1 
org.mockito.exceptions.verification.TooManyActualInvocations:
mInterface$MockitoMock$b85WZhRq.add(0);
Wanted 1 time:
-> at MyTest.testSpyMockInterfaceMockito5(MyTest.java:21)
But was 2 times:
-> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-> at MyTest.testSpyMockInterfaceMockito5(MyTest.java:18)

## mockito 4.4.0 ok
## mockito-subclass 5.1.1 ok
 */
@sharpau
Copy link

sharpau commented Feb 17, 2023

I have the same issue on upgrade. I believe the issue is using spy(mock(Foo.class)) - I see this in your upgrade and in the test that failed on my upgrade. I removed the outer spy() and my test works as expected again. Spying on a mock doesn't make sense, I don't think - imo Mockito should error in this scenario.

@bmaggi
Copy link
Contributor Author

bmaggi commented Feb 21, 2023

Indeed removing the spy() made the test pass.

Still the current message feels wrong, an clear error indicating that spying a mock is forbidden would be better.

@TimvdLippe
Copy link
Contributor

Spying of mocks is not supported. If you would like to improve the messaging here, I would be happy to review a PR for it. You will need to update spy(T object) (

public static <T> T spy(T object) {
) to check for isMock:
public static boolean isMock(Object mock) {

@xgrimauu
Copy link

Can someone help me understand why this only happens with interfaces and not with implementations? E.g.

This breaks as @bmaggi described:

List<Integer> spy = Mockito.spy(Mockito.mock(List.class));
spy.add(1);
verify(spy).add(1);

This seems to work though:

List<Integer> spy = Mockito.spy(Mockito.mock(LinkedList.class));
spy.add(1);
verify(spy).add(1);

What makes me think that if we add a validation to the spy(T Object) method, we might break some previously working code like the one in the second example.

@bmaggi
Copy link
Contributor Author

bmaggi commented Mar 27, 2023

@xgrimauu Indeed it's a good point, if an exception is raised it will break your second example (that is currently working)

For the moment, I see these options:

  1. Raise an invalid Argument Exception for all mock(will break test with spy(mock(class)))
  2. Raise an exception only for mocked Interface (just need to find how ;))
  3. Add a logging message warn
  4. Fix the behavior for mocked interface

@TimvdLippe What would be the best option ?

bmaggi added a commit to bmaggi/mockito that referenced this issue Apr 3, 2023
@bmaggi
Copy link
Contributor Author

bmaggi commented Apr 3, 2023

I implemented a draft here

Only raise exception on interface.

Any suggestion ?

bmaggi added a commit to bmaggi/mockito that referenced this issue Apr 28, 2023
bmaggi added a commit to bmaggi/mockito that referenced this issue Apr 28, 2023
@bmaggi
Copy link
Contributor Author

bmaggi commented Apr 28, 2023

For information : Following the comment in the PR, I changed the code to forbid all mock.

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

No branches or pull requests

4 participants