我想用Spock测试我的Java应用程序。我有一个类AmiPlugin.java
,通过构造函数注入有两个依赖项:
@Autowired
AmiPlugin(final EC2InstanceContextProvider contextProvider,
final ViolationSink violationSink) {
super(contextProvider);
this.violationSink = violationSink;
}
我的groovy测试看起来像这样:
@ContextConfiguration(loader = SpringApplicationContextLoader , classes = [AmiPlugin.class])
class AmiPluginSpec extends Specification{
@Autowired
AmiPlugin amiPlugin;
def "Test if plugin supports the right Cloudtrail events"(String event, Boolean supports){
expect:
amiPlugin.supportsEventName().test(event) == supports
where:
event | supports
"RunInstances" | true
"StartInstances" | false
"TerminateInstances" | false
"StopInstances" | false
"Foobar" | false
}
但是,运行此操作会给我一个NoSuchBeanDefinitionException
。在jUnit中,我会在同一个文件中使用一个带有@configuration
的静态类,它返回所需的模拟,但是它不起作用。
使用
@Bean
EC2InstanceContextProvider ec2InstanceContextProviderMock(){
EC2InstanceContextProvider provider = Mock()
return provider
}
也无效。
如何在Spock中自动装配模拟?
编辑当然
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228)
at org.spockframework.spring.SpringTestContextManager.prepareTestInstance(SpringTestContextManager.java:49)
at org.spockframework.spring.SpringInterceptor.interceptSetupMethod(SpringInterceptor.java:42)
at org.spockframework.runtime.extension.AbstractMethodInterceptor.intercept(AbstractMethodInterceptor.java:28)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'amiPlugin': Unsatisfied dependency expressed through constructor argument with index 0 of type [org.zalando.stups.fullstop.plugin.EC2InstanceContextProvider]: No qualifying bean of type [org.zalando.stups.fullstop.plugin.EC2InstanceContextProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.zalando.stups.fullstop.plugin.EC2InstanceContextProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766)
at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
at org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 13 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.zalando.stups.fullstop.plugin.EC2InstanceContextProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 31 more
答案 0 :(得分:1)
您正在寻找的是分离的模拟,可以让您创建超出规范的模拟。 https://github.com/spockframework/spock/issues/86 - 能够将Spock模拟注入Spring bean。在那里你可以找到一个黑客如何做到这一点。
更新2017-03-25 :在1.1版的Spock中添加了对分离的模拟的完全支持。可以在in the documentation和this SO answer中找到用法示例。
答案 1 :(得分:0)
您可以在Spock 1.2中使用SpringBean注释:https://objectpartners.com/2018/06/14/spock-1-2-annotations-for-spring-integration-testing/
因此您的代码将变为:
@ContextConfiguration(loader = SpringApplicationContextLoader , classes = [AmiPlugin.class])
class AmiPluginSpec extends Specification{
@SpringBean
AmiPlugin amiPlugin = Mock()
def "Test if plugin supports the right Cloudtrail events"(String event, Boolean supports){
expect:
amiPlugin.supportsEventName().test(event) == supports
where:
event | supports
"RunInstances" | true
"StartInstances" | false
"TerminateInstances" | false
"StopInstances" | false
"Foobar" | false
}
您不再需要其他配置类,因为该模拟由Spock直接注入到Spring上下文中