-
Notifications
You must be signed in to change notification settings - Fork 41.1k
@MockBean doesn't work with @Async annotated services #6405
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
Comments
It looks like the A workaround is to force the creation of CGLib proxies:
|
The same problem occurs if the mocked bean is created manually so |
So that means I basically have two options: Change the behavior of the application by changing the annotation on the application class or adding an additional configuration with "test" profile or something like that? Just adding I understand what's happening and the workaround would work for me I guess but I guess that behavior would come as a surprise to many. |
Hm… I tried to implement the workaround in my project and not only in the demo: |
Well, that's exactly the same root cause... |
Agreed. We need to do something better here, I'm just not sure what yet.
This shouldn't be (much of) a change in behaviour. You'll end up with a different type of proxy (CGLib rather than JDK) but that shouldn't matter to your application.
That may work, although I'm not sure which
Not sure I've understood this. You already have
Caching uses proxies too and, in its default configuration, it uses JDK proxies. It has a |
Thanks, Andy! As well as I understand
it will probably raise some questions…
If I have
I was hoping I could overwrite without introducing new configuration classes by adding it to the test class itself. |
I wouldn't recommend doing that. It doesn't feel like a good idea to be running your tests with different configuration from normal runtime. It feels like the best that we can do here is to make it more obvious that you need to configure |
I've generally found |
@philwebb What does that mean:
From the Anyway, why don't I get CGLIB proxies anyway? The service in the example doesn't implement any interface… |
@michael-simons The service doesn't directly implement an interface, but when
|
@philwebb my take on this would be to copy/paste your last comment (with some polishing) in the doc. |
I disagree, for now at least. Users shouldn't have to know any of that. The ideal is that it just works. I doubt we'll get there in Boot 1.4 and Framework 4.3, but there's still plenty of scope for improvement. I'd like to wait and see what SPR-14478 brings us. |
Thanks everybody, for the explanation and workaround and also for the last comment, that is exactly which I would expect as a user, @wilkinsona. |
With the latest Spring Framework 4.3.2 snapshot, the provided example passes even with |
@wilkinsona good news! But you mean |
@michael-simons Sorry. I meant |
If I update the example so that
I think we should add a |
Hello, I experience issues which seem to be closely related to this thread in Spring Boot 1.4.0.RELEASE - should I go on or should I open a new issue for this? Thanks |
@WalternativE Thanks for asking. Please open a new issue, ideally with a small sample that reproduces the problem |
Hi @WalternativE Would you please link this? I think just stumbled onto something as well and I wanna check if it's the same. |
Post-processing of mocked beans causes a number of problems: - The mock may be proxied for asynchronous processing which can cause problems when configuring expectations on a mock (spring-projectsgh-6573) - The mock may be proxied so that its return values can be cached or so that its methods can be transactional. This causes problems with verification of the expected calls to a mock (spring-projectsgh-6573, spring-projectsgh-5837) - If the mock is created from a class that uses field injection, the container will attempt to inject values into its fields. This causes problems if the mock is being created to avoid the use of one of those dependencies (spring-projectsgh-6663) - Proxying a mocked bean can lead to a JDK proxy being created (if proxyTargetClass=false) as the mock implements a Mockito interface. This can then cause injection failures as the types don’t match (spring-projectsgh-6405, spring-projectsgh-6665) All of these problems can be avoided if a mocked bean is not post-processed. Avoiding post-processing prevents proxies from being created and autowiring from being performed. This commit avoids post-processing by registering mocked beans as singletons rather than via a bean definition.
I ran into the same issue. after add "proxyTargetClass = true" it works. |
Post-processing of mocked beans causes a number of problems: - The mock may be proxied for asynchronous processing which can cause problems when configuring expectations on a mock (gh-6573) - The mock may be proxied so that its return values can be cached or so that its methods can be transactional. This causes problems with verification of the expected calls to a mock (gh-6573, gh-5837) - If the mock is created from a class that uses field injection, the container will attempt to inject values into its fields. This causes problems if the mock is being created to avoid the use of one of those dependencies (gh-6663) - Proxying a mocked bean can lead to a JDK proxy being created (if proxyTargetClass=false) as the mock implements a Mockito interface. This can then cause injection failures as the types don’t match (gh-6405, gh-6665) All of these problems can be avoided if a mocked bean is not post-processed. Avoiding post-processing prevents proxies from being created and autowiring from being performed. This commit avoids post-processing by registering mocked beans as singletons as well as via a bean definition. The latter is still used by the context for type matching purposes. Closes gh-6573, gh-6663, gh-6664
Hello everybody,
I want to test a MVC @controller with 1.4.0.RC1 using @WebMvcTest. The controller depends on a service which as an @async method:
The service:
Test fails with
My first guess that this is related to #5837 or similar. Throwing @EnableAsync at the test didn't help either, using a separate context configuration would defeat the purpose of WebMvcTest i guess
Example project is attached mock_async_proxy_bug.tar.gz
Actual use case was writing a test for this controller in preparation for 1.4.
Thanks,
Michael.
The text was updated successfully, but these errors were encountered: