1

I am using spring boot with jpa and spock. I want to assert that certain calls were made to the repo as a functional test, so a Mock won't do (I need to verify that a native query works with certain test data in the DB).

I have tried a @SpringBootTest with the field:

@SpringSpy
MyJpaRepository repo

and within the test method:

interaction {
        1 * repo.someMethod(_) 
}

where MyJpaRepository extends JpaRepository<Foo, Long>, but when I run the test I get:

Cannot create mock for class com.sun.proxy.$Proxynnn because Java mocks cannot mock final classes. If the code under test is written in Groovy, use a Groovy mock.

Other than this error, all my functional tests work, so it's not a config issue.

How can I spy on an @Autowired bean?

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • Your error message looks like you are trying to mock an object which is already a dynamic proxy as suggested by `com.sun.proxy.$Proxynnn`. So you are not directly spying on a `MyJpaRepository` instance but on a dynamic proxy wrapping it for whatever Spring-ish purpose (such as AOP or transactions). As Spock's mock objects are also dynamic proxies, the framework needs to be able to work with non-final classes. It looks like the dynamic proxy is final, though. Somehow you need to make sure to spy on the original `MyJpaRepository` object, not on its proxy. – kriegaex Feb 12 '20 at 06:34
  • @kriegaex Yes, that's all true and that's my question: How can I spy on the actual bean in the app context, which is a proxy? There is no "original" object - spring builds its own proxy class, and that's the one I would like to spy on. – Bohemian Feb 12 '20 at 06:37
  • Ah, `MyJpaRepository extends JpaRepository`, not `implements`. So you are actually trying to spy on an interface type, not on a class type. Actually you can only spy on an instance of a concrete class type. Spying on an interface would not make sense anyway. BTW: Of course there is always an "original" object instance for each Spring proxy because dynamic proxies use a delegation pattern. – kriegaex Feb 12 '20 at 07:03
  • @kriegaex why would spying on an instance of an interface, which is what the jpa bean is, make no sense? – Bohemian Feb 12 '20 at 07:07
  • Maybe we misunderstand each other, I was talking about [normal Spock spies](http://spockframework.org/spock/docs/1.3/all_in_one.html#Spies). You cannot directly create a spy for an interface because an interface does not have any functionality. As for `@SpringSpy`, I never used Spring actively and thus have no experience with how this works, I can just tell you what the technical problem is. You might want to try to use the concrete implementation type instead of the interface type in your test. Whatever limitation you are hitting here, you cannot mock/spy a final class and need a workaround. – kriegaex Feb 12 '20 at 07:17
  • 1
    Maybe an additional `@UnwrapAopProxy` would help beside `@SpringSpy`? Just guessing after seeing [this sample test](https://github.com/spockframework/spock/blob/master/spock-spring/src/test/groovy/org/spockframework/spring/mock/imported/SpringSpyWithAopProxyTests.groovy). Probably you as a Spring user understand more about it than I, I only know about dynamic proxies and how they are used in Spring because I often answer Spring AOP questions. – kriegaex Feb 12 '20 at 07:34
  • @kriegaex thanks for the ideas. I tried `@UnwrapAopProxy` but same error. – Bohemian Feb 12 '20 at 22:24
  • Then - a person with a reputation as high as yours might have expected this suggestion - I kindly ask you to provide an [MCVE](https://stackoverflow.com/help/mcve) reproducing your problem on GitHub and linking to it from here, so the people who want to help you can analyse your situation and check your whole configuration. Your little snippets are not conducent to more than speculation, and speculate I did. ;-) – kriegaex Feb 13 '20 at 00:22
  • @Bohemian in short you can't. You can use a normal `Mock` for the repository though. – Leonard Brünings Feb 15 '20 at 19:42
  • @kriegaex thank you - `@UnwrapAopProxy` actually did solve a similar problem for me. – dan Dec 25 '21 at 03:33

0 Answers0