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

allow to use different mocking librarires in spring-boot-test for @MockBean #9372

Closed
pchudzik opened this issue May 31, 2017 · 7 comments
Closed
Labels
status: declined A suggestion or change that we don't feel we should currently apply

Comments

@pchudzik
Copy link

pchudzik commented May 31, 2017

Right now only way of mocking stuff in spring-boot-tests is using mockito which is awesome if you are writing your tests in java but if you are using spock then you might want to use spock mocks. With spock 1.1 one can create detachable mocks not bounded to Specification class instance. It would be great if it would be possible to allow plug in different mocking framework. Spring will ship with mockito as it is now, but spock will be able to provide some classes which will provide custom mock factory.

I've been trying to investigate this issue on my own (and do it in my project) and here is what I found out.

Class org.springframework.boot.test.mock.mockito.MockitoPostProcessor would be good entry point to start. There is pretty promising method org.springframework.boot.test.mock.mockito.MockitoPostProcessor#createMock (with spies it is more complicated and I stopped searching after I tripped over this one), but classes MockDefinition and SpyDefinition are package private (for starters) and method createMock is protected final so it is impossible to override.

imho mock creation should be abstracted somehow and it should open MockitoPostProcessor (not only mockito any more) for different mocking libraries (like spocks detachable beans).

What do you think about it? Would you consider accepting PR which will mess around in mockito package

@wilkinsona
Copy link
Member

Thanks for the suggestion, but my feeling is that we don't want to introduce the extra complexity that supporting multiple mocking libraries would require. Let's see what the rest of the team think.

@wilkinsona wilkinsona added the for: team-attention An issue we'd like other members of the team to review label Jun 1, 2017
@philwebb
Copy link
Member

philwebb commented Jun 2, 2017

I'm inclined to agree with Andy. Adding Mockito support was painful enough and I don't particularly want to make that code any more complex that it has to be. I'd like to see Spock support but I think it should be handled outside of Spring Boot core.

If anyone is interested in starting a new Apache 2.0 project they are welcome to fork the existing Mockito code. We can also look into donating it under a different license if necessary.

@philwebb philwebb closed this as completed Jun 2, 2017
@philwebb philwebb added status: declined A suggestion or change that we don't feel we should currently apply 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 Jun 2, 2017
@pchudzik
Copy link
Author

If anyone stumbles on this in the future I wanted to let you know that I've created springmock library which allows to inject mocks created by any mocking library (in theory, in practice I've got support for spock mocks and mockito and infrastructure to plugin more). Since I've got minimal set of features you can use it along with springboot @MockBean and @SpyBean.

More on my blog and project github page

@leonard84
Copy link
Contributor

@wilkinsona / @philwebb I've taken over @twicksell attempt to integrate this support into Spock itself and I've some questions:

  • Injecting mocks via @MockBean modifies the application context, so the context implicitly becomes dirty
    • I didn't find any cleanup code in https://github.com/spring-projects/spring-boot/tree/master/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito is this handled somewhere else?
    • How does it affect context caching, are the mock annotations included into the cache lookup?
  • If context caching is active, then parallel executed tests would share the same context, mocks however don't really work in a parallel environment. Do you guys have some suggestions here, or do we have to enforce sequential execution?
  • You'd be fine if Spock would take this code and integrate it into the spock-spring (or similar) module?

@wilkinsona
Copy link
Member

How does it affect context caching, are the mock annotations included into the cache lookup?

Yes. The mock beans affect the contents of the context so they also affect the key that's used for the cache.

If context caching is active, then parallel executed tests would share the same context, mocks however don't really work in a parallel environment. Do you guys have some suggestions here, or do we have to enforce sequential execution?

We haven't worried about parallel execution of tests in the same JVM/ClassLoader. Either forcing sequential execution or parallelising using multiple JVMs would be perfectly fine

You'd be fine if Spock would take this code and integrate it into the spock-spring (or similar) module?

Yes, that's fine. All the code is Apache V2 licensed and so is Spock so you're free to do whatever you'd like.

@pchudzik
Copy link
Author

@wilkinsona, @leonard84 Maybe you guys will be interested in springmock?
Right now I have working support for Mockito and Spock mocks/spies springmock infrastructure will inject them into Spring integration tests. I'll be happy to integrate/merge with Spring and/or Spock if you guys are interested.

@leonard84 maybe instead of coping spring behavior yet again we can figure something out together? Maybe you'll be interested in merging something from springmock into Spock or delegating some work to springmock? Spock is awesome so I'd be happy to help just let me know if you are interested :)

@wilkinsona I know that springmock does not support @MockBean nor @SpyBean annotations but it is by design. I wanted to keep it separated to allow usage of springmock in existing projects and avoid conflicts. Maybe spring team will be interested in taking some code from springmock to allow other mocks providers work with spring? Please consider starting up yet another project in the spring-boot portfolio or merging springmock-infrastructure into spring-boot-test. Spring is also awesome project so I'll be happy to help just let me know if you are interested :)

@leonard84
Copy link
Contributor

@pchudzik I'm aware of your project, I'm going to look at both sources. However, I also want to explore some different approaches, e.g. creating proxies in the spring context and using the full power of the existing Mock/Stub/Spy methods to create mocks without overloading the annotations with a plethora of options. This would also keep the mocks used in the class unwrapped of AopProxies such as transactional, while still being advised in the spring context.

@SpringMock
Service service = Mock() {
  getSomething() >> "hello"
}

My goal would be to integrate it into spock-spring, without the need to for an external module. I've send you an invite to the Spock slack channel where we can discuss it further. If you @wilkinsona or @philwebb want to join the Spock slack channel as well just say the word, we are always interested in getting key developers as advisors or contributors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

5 participants