I have a Spring-Data Repo
interface MyRepo extends CrudRepository<String, Entity> {
default Entity richSave(Entity entity) {
return save(entity);
}
}
I want to verify that richSave delegates to save method
@Spy
@Autowired
MyRepo repo;
@Test
void myTest() {
var entity = mock(Entity.class);
repo.richSave(entity);
verify(repo).save(entity)
}
These kinds of tests have been passing flawlessly on Java 11, Spring Boot 2.3.3.RELEASE, Mockito 4.11.0
When I decided to upgrade to Java 17, Spring Boot 2.7.7, Mockito 5.0.0 (Released 5 days ago, key point is mock-maker-inline is now a default. Interoperability with Mockito 4 is promised. Version of Mockito in irrelevant in this case)
I began to observe such kinds of errors:
Argument passed to verify() is of type $Proxy171 and is not a mock!
I started a research:
First solution that I found is using @SpyBean
I declined this idea because:
1. I want to run tests in Parallel
2. New spy instance for each test method is desired (It's not fun to scan through 40+ invocations)
3. @SpyBean doesn't detect invocation of save method
Second:
@BeforeEach
void setUp() {
repository = mock(MyRepo.class, delegatesTo(repository));
}
Doesn't detect invocation of save
Third:
@BeforeEach
void setUp() {
repository = spy(repository);
}
Almost the same error message as in a variant with @Spy annotation:
Argument passed to Mockito.mockingDetails() should be a mock, but is an instance of class jdk.proxy2.$Proxy142
I tried to look into setUp method with debugger:
1. repository remains a Proxy
2. Mockito.mockingDetails(repository).isSpy() - false
I suppose the problem is on the Mock-Maker part (I didn't exclude MockMaker file) Byte-Buddy is of the latest version available (1.12.22)
I tried Injecting bean via constructor, this didn't help as well
If reproduction repo is required - I can provide one
Thanks!
P.S.
new InlineByteBuddyMockMaker().isTypeMockable(repository.getClass()).mockable() - true
Comment From: philwebb
This sounds like it could be a Mockito issue. I don't understand why repository = spy(repository); would return something where isSpy() returns true. You could try to replicate the issue without Spring being involved.
If reproduction repo is required - I can provide one
That would be helpful. Thanks.
Comment From: ReDestroyDeR
@philwebb I made working examples with Mongo and Postgres https://github.com/ReDestroyDeR/SpringSpying Tests pass on Java 11 and fail on Java 17
I suppose it's due to changes in internal java api, or change in proxying mechanism of Spring
I tried to reproduce with simple Java Interfaces and Proxies, and I couldn't get it to work (Child interface calling method of a superinterface, which is defined as proxy)
Didn't include that example
I understand that Boot 2.3.3.RELEASE had been discontinued in support, but anyway, It's the stack we currently use and I hope we can find an answer to this problem (For other people, finding out an answer)
By the way, I also understand that it's bad quality of tests for repositories (verifying calls and etc.) caused by bad design decisions, and It should be tested using only state-validation (assertions)
Hope it helps
Thanks!
Comment From: ReDestroyDeR
UPD: Also added test cases for InlineByteBuddyMockMaker and .isSpy()
Comment From: ReDestroyDeR
Any progress on this matter? Thanks.
Comment From: wilkinsona
I've spent some time looking at this and I've found it difficult to match the behavior of the sample with the description of the problem. The most notable difference is that the tests in the sample fail whether or not they're run in parallel. The title of the issue suggested to me that the problem only occurs with parallel execution.
There's also some complexity in the sample that may not be required. For example, the sample uses both JPA and Mongo (including using JPA annotations on the entity that's stored in Mongo). It also uses Lombok which inhibits debugging. Can you please reduce the sample to the absolute bare minimum (in terms of dependencies) that's required to reproduce the problem. For example, if it occurs without Lombok, please remove Lombok. If it occurs when only Mongo is used, please remove JPA.
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-projects-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.