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
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.
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.
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
@wilkinsona / @philwebb I've taken over @twicksell attempt to integrate this support into Spock itself and I've some questions:
@MockBean modifies the application context, so the context implicitly becomes dirtyhttps://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?
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.
@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 :)
@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.
Most helpful comment
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