I'm seeing the following exception when using @SpyBean for a CrudRepository in my Integration-Tests:

org.mockito.exceptions.base.MockitoException: VerificationStartedEvent.setMock() does not accept parameter which is not a Mockito mock.
  Received parameter: org.springframework.data.jpa.repository.support.SimpleJpaRepository@1adc1d78.
  See the Javadoc.
    at org.springframework.boot.test.mock.mockito.SpyDefinition$SpringAopBypassingVerificationStartedListener.onVerificationStarted(SpyDefinition.java:114)

What I'm trying to do is instrument the repository to fail at a certain call to test the error handling behavior. So the definition of the field in question is as simple as it gets:

@SpyBean
private MyCrudRepository myCrudRepository;

I can use the Spy correctly for everything, with the exception of verifying whether the function was actually called, which gives me the above exception. I'm using verify like this:

Mockito.verify(myCrudRepository, Mockito.times(1)).save(Mockito.any());

As far as I can see, that is because in SpyDefinition.SpringAopBypassingVerificationStartedListener:114 the actual object is being presented to the VerificationStartedEvent, which actually expects a mock.

Or is that an unsupported use-case or am I spying on the repository in a wrong way?

Comment From: wilkinsona

Or is that an unsupported use-case or am I spying on the repository in a wrong way?

@RobertZenz, unfortunately it's hard to say as I'm not sure that I have understood exactly what you're trying to do. Could you please provide a complete yet minimal sample that reproduces the problem? You could share it with us by zipping it up and attaching it to this issue or pushing it to a separate repository on GitHub.

Comment From: RobertZenz

It's exactly as simple as I wrote to reproduce:

@SpringBootTest
public class Testcase {
    @SpyBean
    private MyCrudRepository myCrudRepistory;

    @Test
    public void test() {
        Mockito.verify(myCrudRepistory, Mockito.times(1)).save(Mockito.any());
    }
}
public interface MyCrudRepository extends CrudRepository<MyModelClass, BigDecimal> {
}

Comment From: wilkinsona

Thanks, but that isn't sufficient for us to be certain that we're looking at the same problem as you are seeing. For example, you haven't told us which version of Spring Boot you're using or of any other dependencies. If you would like us to spend some more time investigating, please spend some time providing a complete yet minimal sample that reproduces the problem. As I said above, you can share it with us by zipping it up and attaching it to this issue or pushing it to a separate repository on GitHub.

Comment From: RobertZenz

Thanks, but that isn't sufficient for us to be certain that we're looking at the same problem as you are seeing. For example, you haven't told us which version of Spring Boot you're using or of any other dependencies.

Given that I've pointed you at the exact line that is the problem in HEAD, I'd say "the latest".

But I'll throw something together...

Comment From: RobertZenz

This is a simple example project which shows this exception.

Comment From: wilkinsona

Thanks for the sample. It's revealed that you're using Mockito's inline mock maker, making this a duplicate of https://github.com/spring-projects/spring-boot/issues/22416.

Comment From: ractive

@wilkinsona I just ran into the same issue with spring 2.4. It seems that this issue was not a duplicate of https://github.com/spring-projects/spring-boot/issues/22416 but still exists. It seems that it's not possible to use a spring-data repository as a @SpyBean. I have taken the example of @RobertZenz from above and updated it to spring 2.4 to show that the error still exists: https://github.com/ractive/spring-boot-gh-23708

Will you reopen this issue or shall I create a new one?

Comment From: wilkinsona

Interesting, thanks. I'll reopen it and we can take another look. There may also be some overlap with https://github.com/spring-projects/spring-boot/issues/7033. Unfortunately, @SpyBean and Spring Data JPA don't play together very nicely at the moment.

Comment From: ractive

Interesting, thanks. I'll reopen it and we can take another look. There may also be some overlap with #7033. Unfortunately, @SpyBean and Spring Data JPA don't play together very nicely at the moment.

Thanks for getting into this issue again.

BTW: We're using spring-data-mongo and see exactly the same issue.

Comment From: ractive

Another thing: In our case it worked with Spring Boot 2.3 and mockito 3.2.0 with:

    @SpyBean(proxyTargetAware = false)
    private MyRepository myRepository;

    @Test
    void someTest() {
        ....
        verify(myRepository).findById(...):
    }

With Spring 2.4 it then fails with the following error:

org.mockito.exceptions.misusing.NotAMockException: 
Argument passed to verify() is of type $Proxy74 and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
    verify(mock).someMethod();
    verify(mock, times(10)).someMethod();
    verify(mock, atLeastOnce()).someMethod();

    at mockfailure.MockfailureTest.test(MockfailureTest.java:18)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
.....

Comment From: wilkinsona

I have a possible fix for #7033 which appears to fix https://github.com/ractive/spring-boot-gh-23708. The spy is successfully created (with or without proxyTargetAware = false). The test then fails:

org.mockito.exceptions.verification.WantedButNotInvoked: 

Wanted but not invoked:
myCrudRepository.save(
    <any mockfailure.data.MyModelClass>
);
-> at mockfailure.MockfailureTest.test(MockfailureTest.java:18)
Actually, there were zero interactions with this mock.

    at mockfailure.MockfailureTest.test(MockfailureTest.java:18)

However, this is to be expected as nothing is interacting with the repository.

The test passes with a modification to the app such that MyCrudRepository.save(MyModelClass) is called.

As a result of the above, I'm going to close this one as a duplicate of #7033