Spock: Ability to inject Spock mocks as Spring beans

Created on 13 May 2015  路  9Comments  路  Source: spockframework/spock

There was an issue on the old tracker referenced in this SO question that doesn't appear to have been migrated. Essentially, for tests that require starting up a nontrivial application context, it would be extremely helpful to be able to create a Spock mock and easily register it as a Spring bean (especially when using Spring Boot for testing).

new feature

Most helpful comment

Hi as my request in spring was rejected I've decided to do something about it and as a result I've created springmock library which allows to inject spock mocks into spock spring integration tests.

More on my blog and on the project github page

All 9 comments

This is implemented by #17

Using a "pure Spring" approach, this is pretty easy:

def parentAppCtx = new StaticApplicationContext()
parentAppCtx.beanFactory.registerSingleton("myBean", Mock(MyClass))
parentAppCtx.refresh()
def appCtx = new ClassPathXmlApplicationContext("spring-config.xml", parentAppCtx)

@jdigger although this might work, it is quite limited, since you need to reload the application context for each Spec/Feature. We have a rather costly application context and it would increase our testing time tremendously to recreate it all the time.

The latest Spring Boot 1.4 Test Support goes a long way in this direction with its new @MockBean annotation. However, it is backed by Mockito.

import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.mock.mockito.MockBean
import spock.lang.Specification

@ContextConfiguration // should not be required, but had to include this for Spock to startup the Spring context
@SpringBootTest
class MySpec extends Specification {
    @MockBean
    MyBean mockOfMyBean
}

Spock support has a little catching up to do with the new cool Spring Boot 1.4 testing.

@jgriff spock-1.1-rc1 already includes detached mock support.

In regards to @MockBean my comment above still holds AFAIK. If it is replacing beans in an already created application context it needs to recreate all beans that have dependencies on it and the context is only valid for this one class. This disables cached-context reuse between test classes which can have a serious impact on your test run times.
However, I haven't looked too deeply into the actual implementation and if they somehow got around that, then maybe we can adopt it for spock mocks as well.

I don't really know how you guys do things in spock because I use groovy only for writing tests, but I've been investigating it on spring side, and I think that spring-boot-test is not ready to be plugged with different mocking framework.

I wanted to inject spock mocks using existing spring infrastructure and since it's not yet possible here is what I was able to find out, maybe it will be helpful to someone...

Class org.springframework.boot.test.mock.mockito.MockitoPostProcessor would be pretty 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.

Based on this in order to implement you would be forced to completely mimic MockitoPostProcessor behavior and logic in order to replace two functions responsible for mock/spy creation which is far from anything good...

imho before trying to do it in spock from scratch some changes should be made in spring-boot-test itself which will allow to plugin other mocking frameworks, and then custom implementation can be introduced in spock which will use DetachableMocks without messing with whole spring infrastructure and beans creation process.

edit: I've created issue in spring-boot.

Hi as my request in spring was rejected I've decided to do something about it and as a result I've created springmock library which allows to inject spock mocks into spock spring integration tests.

More on my blog and on the project github page

@pchudzik nice work, I noticed you had some comments, e.g., Spock doesn't support additional interfaces for mocks yet, feel free to create some issues.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

YaroSpace picture YaroSpace  路  7Comments

robfletcher picture robfletcher  路  7Comments

donbeave picture donbeave  路  5Comments

wites342 picture wites342  路  4Comments

minjing picture minjing  路  4Comments