用Spock测试Spring中的Mock Bean

时间:2014-04-03 15:04:44

标签: spring spock

我遇到spock不允许在规范之外创建Mocks的问题 - How to create Spock mocks outside of a specification class?

这似乎仍然很突出,所以我要问的是,给我一个复杂且嵌套的DI图是什么才是最有效的方式来注入'图中深处的模拟表示?

理想情况下,我为正常部署设置了一个bean定义,在运行单元测试时有另一个bean定义设置,这个定义设置为适用的Mocks

e.g。

@Configuration
@Profile("deployment")
public class MyBeansForDeployment {

   @Bean
   public MyInterface myBean() {
       return new MyConcreateImplmentation();
   } 

}

&安培;&安培;

@Configuration
@Profile("test")
public class MyBeansForUnitTests {

   @Bean
   public MyInterface myBean() {
       return new MyMockImplementation();
   } 

}

3 个答案:

答案 0 :(得分:1)

你可以尝试实现一个BeanPostProcessor,它将用测试双精度替换你想要的bean,如下所示:

public class TestDoubleInjector implements BeanPostProcessor {
...

private static Map<String, Object[]> testDoubleBeanReplacements = new HashMap<>();

public void replaceBeanWithTestDouble(String beanName, Object testDouble, Class testDoubleType) {
    testDoubleBeanReplacements.put(beanName, new Object[]{testDouble, testDoubleType});
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (testDoubleBeanReplacements.containsKey(beanName)) {
        return testDoubleBeanReplacements.get(beanName)[TEST_DOUBLE_OBJ];
    }

    return bean;
}

在测试中,在初始化应用程序上下文之前设置如下所示的模拟。确保将TestDoubleInjector作为bean包含在测试上下文中。

TestDoubleInjector testDoubleInjector = new TestDoubleInjector()
testDoubleInjector.replaceBeanWithTestDouble('beanToReplace', mock(MyBean.class), MyBean.class)

答案 1 :(得分:1)

从Spock 1.1开始,您可以在规范类之外创建模拟(分离的模拟)。其中一个选项是DetachedMockFactory。请查看the documentationmy answer to the question you linked

答案 2 :(得分:-1)

可以使用HotSwappableTargetSource

完成
@WebAppConfiguration
@SpringApplicationConfiguration(TestApp)
@IntegrationTest('server.port:0')

class HelloSpec extends Specification {

@Autowired
@Qualifier('swappableHelloService')
HotSwappableTargetSource swappableHelloService

def "test mocked"() {
  given: 'hello service is mocked'
  def mockedHelloService = Mock(HelloService)
  and:
  swappableHelloService.swap(mockedHelloService)

  when:
  //hit endpoint
  then:
  //asserts 
  and: 'check interactions'
  interaction {
      1 * mockedHelloService.hello(postfix) >> { ""Mocked, $postfix"" as String }
  }
  where:
  postfix | _
  randomAlphabetic(10) | _
}
}

这是TestApp(覆盖你想用代理模拟的bean)

class TestApp extends App {

//override hello service bean
@Bean(name = HelloService.HELLO_SERVICE_BEAN_NAME)
public ProxyFactoryBean helloService(@Qualifier("swappableHelloService") HotSwappableTargetSource targetSource) {
def proxyFactoryBean = new ProxyFactoryBean()
proxyFactoryBean.setTargetSource(targetSource)
proxyFactoryBean
}

@Bean
public HotSwappableTargetSource swappableHelloService() {
  new HotSwappableTargetSource(new HelloService());
}
}

看一下这个例子https://github.com/sf-git/spock-spring

相关问题