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

Mocking session scoped spy bean calls real method #17817

Closed
cdalexndr opened this issue Aug 8, 2019 · 13 comments
Closed

Mocking session scoped spy bean calls real method #17817

cdalexndr opened this issue Aug 8, 2019 · 13 comments
Assignees
Labels
type: bug A general bug
Milestone

Comments

@cdalexndr
Copy link
Contributor

Trying to mock a @SessionScope in a test by autowiring it using @SpyBean and then mocking using doReturn(..).when(sessionScopedBean).method(any()) calls the real method with null argument instead of silently registering mock.
Removing @SessionScope from the bean resolves this issue.

Spring boot 2.1.6.RELEASE

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 8, 2019
@mbhave
Copy link
Contributor

mbhave commented Aug 9, 2019

@cdalexndr Please provide a minimal sample that we can use to reproduce the issue.

@mbhave mbhave added the status: waiting-for-feedback We need additional information before we can continue label Aug 9, 2019
@cdalexndr
Copy link
Contributor Author

https://github.com/cdalexndr/spring-boot-issue-17817
Just run gradlew test
Note that removing @SessionScope fixes test.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Aug 10, 2019
@blindpirate
Copy link
Contributor

I did some debugging. Seems like that @SessionScope is enhanced by Spring so every method in it becomes final, thus Mockito can't enhance it again. I'm wondering, why does Spring make all methods final when enhancing the bean? Can we somehow only make the injected methods final, but keep all declared methods non-final?

@wilkinsona wilkinsona self-assigned this Aug 21, 2019
@wilkinsona
Copy link
Member

Thanks for the sample, @cdalexndr.

When you use @SpyBean, the spy is created via SpyPostProcessor which is an InstantiationAwareBeanPostProcessorAdapter and it is PriorityOrdered with highest precedence. This is intended to ensure that the spy is created before any proxying performed by Spring Framework. It works for @Scheduled, @Async, etc, but it does not work in the case of a scoped proxy as the proxying is done as part of component scanning rather than bean post-processing. Switching to a @Bean method on a @Configuration class does not help as ConfigurationClassBeanDefinitionReader does the same thing.

I can't see a way to fix this without some changes in Spring Framework. Flagging for team attention in case I've missed something.

@wilkinsona wilkinsona added for: team-attention An issue we'd like other members of the team to review and removed status: feedback-provided Feedback has been provided labels Aug 21, 2019
@wilkinsona
Copy link
Member

We might be able to get the bean definition for the target as both it and the scoped proxy are added to the bean factory. We could perhaps then replace the target with the definition for the spy.

@wilkinsona wilkinsona added type: bug A general bug and removed for: team-attention An issue we'd like other members of the team to review status: waiting-for-triage An issue we've not yet triaged labels Aug 23, 2019
@wilkinsona wilkinsona added this to the 2.1.x milestone Aug 23, 2019
@wilkinsona
Copy link
Member

wilkinsona commented Aug 23, 2019

@cdalexndr While we're working on a fix, you can work around the problem by spying upon the scoped proxy's target which is the underlying SessionScopeBean instance that has not be proxied and, therefore, can be spied upon:

@SpyBean(name="scopedTarget.sessionScopedBean")

@elxnis
Copy link

elxnis commented Nov 13, 2019

Hi @wilkinsona ,
could your fix for this cause issues with @SpyBean on @StepScoped beans?
I have spring boot application that uses spring batch, so I have couple beans that are @StepScoped and I am using @SpyBean on them in my tests, but they have started to fail since updating to spring boot 2.1.9.RELEASE from 2.1.7.RELEASE.

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.beanName': Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope

@wilkinsona
Copy link
Member

That looks possible. It's certainly in the same area. Please open a new issue with a small sample that reproduces the issue and we can take a look.

@wilkinsona
Copy link
Member

Please note that, unfortunately, we've had to revert the fix for this issue. The problem can be avoided by adding a dependency on org.mockito:mockito-inline to your application's test dependencies.

@cdalexndr
Copy link
Contributor Author

@wilkinsona if that dependency fixes this issue, shouldn't be added to spring-boot-starter-test to be general available?

@wilkinsona
Copy link
Member

No, I don't think so. It fundamentally changes the way in which Mockito behaves and the Mockito team have chosen to make it opt-in for that reason. If Mockito makes it the default in the future then we would probably do the same in Spring Boot. Until then, I think it should remain opt-in so that users have a natural point at which to consider the implications.

@cdalexndr
Copy link
Contributor Author

@wilkinsona then if the fix was reverted and the workaround cannot be made general available due to side effects, shouldn't this issue be reopened, as a reminder, until a new fix is made?

@wilkinsona
Copy link
Member

We've already made the only "fix" that we can, and that is to add a note to the documentation about mockito-inline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

6 participants