我正在尝试使用Spring Boot,Spock-Spring和Embedded Kafka进行集成测试。我跟着this guide,我找到了#34;当嵌入式代理在随机端口上启动时,我们无法使用src/main/resources/application.yml
属性文件中的修复值。幸运的是,@ClassRule
将spring.embedded.kafka.brokers
系统属性设置为嵌入式代理的地址。"因此我有
@ContextConfiguration
@SpringBootTest(classes = [Application], webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@DirtiesContext
@Stepwise
@ActiveProfiles("test")
class AnIntegrationTest extends Specification {
@Autowired
private KafkaListenerEndpointRegistry kafkaListenerEndpointRegistry
@ClassRule
public static KafkaEmbedded embeddedKafka = new KafkaEmbedded(1, true, "topic")
private KafkaTemplate<String, String> template
def setup() {
Map<String, Object> senderProperties = KafkaTestUtils.senderProps(embeddedKafka.getBrokersAsString())
ProducerFactory<String, String> producerFactory =
new DefaultKafkaProducerFactory<String, String>(senderProperties)
template = new KafkaTemplate<>(producerFactory)
template.setDefaultTopic("topic")
for (MessageListenerContainer messageListenerContainer : kafkaListenerEndpointRegistry
.getListenerContainers()) {
ContainerTestUtils.waitForAssignment(messageListenerContainer, embeddedKafka.getPartitionsPerTopic())
}
}
def "test"() {
given:
template.sendDefault("Hello")
}
}
在application-test.yml
我有
kafka:
bootstrapservers: ${spring.embedded.kafka.brokers}
在应用程序中,我使用spring-kafka
启动了Kafka消费者。
堆栈跟踪是
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.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.spockframework.spring.SpringTestContextManager.prepareTestInstance(SpringTestContextManager.java:50)
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.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:88)
at org.spockframework.runtime.extension.builtin.AbstractRuleInterceptor$1.evaluate(AbstractRuleInterceptor.java:37)
at org.togglz.junit.TogglzRule$1.evaluate(TogglzRule.java:127)
at org.spockframework.runtime.extension.builtin.TestRuleInterceptor.intercept(TestRuleInterceptor.java:38)
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:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'kafkaListenerContainerFactoryConfiguration': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.embedded.kafka.brokers' in value "${spring.embedded.kafka.brokers}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
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:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 19 more
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.embedded.kafka.brokers' in value "${spring.embedded.kafka.brokers}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:236)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
at org.springframework.core.env.AbstractPropertyResolver.resolveNestedPlaceholders(AbstractPropertyResolver.java:227)
at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:84)
at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:61)
at org.springframework.core.env.AbstractEnvironment.getProperty(AbstractEnvironment.java:527)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$1.getProperty(PropertySourcesPlaceholderConfigurer.java:132)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$1.getProperty(PropertySourcesPlaceholderConfigurer.java:129)
at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:81)
at org.springframework.core.env.PropertySourcesPropertyResolver.getPropertyAsRawString(PropertySourcesPropertyResolver.java:71)
at org.springframework.core.env.AbstractPropertyResolver$1.resolvePlaceholder(AbstractPropertyResolver.java:239)
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:147)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:236)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:172)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:831)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1086)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
... 36 more
有没有人有线索?
答案 0 :(得分:2)
我在embeddedKafka.before()
中调用了setup()
。然后spring.embedded.kafka.brokers
已设置并可用。
我不确定,但问题似乎特别是Spock Spring。
答案 1 :(得分:1)
我对Spock不熟悉,但简单的Java JUnit测试工作正常......
@SpringBootApplication
public class So47172973Application {
public static void main(String[] args) {
SpringApplication.run(So47172973Application.class, args);
}
@KafkaListener(topics = "foo")
public void in(String in) {
System.out.println(in);
}
}
和
spring:
kafka:
bootstrap-servers:
- ${spring.embedded.kafka.brokers}
consumer:
group-id: embedded1
auto-offset-reset: earliest
和
@RunWith(SpringRunner.class)
@SpringBootTest
public class So47172973ApplicationTests {
@ClassRule
public static KafkaEmbedded embeddedKafka = new KafkaEmbedded(1, true, "foo");
@Autowired
private KafkaTemplate<String, String> template;
@Test
public void test() throws InterruptedException {
template.send("foo", "bar");
Thread.sleep(10_000);
}
}
要尝试的几件事情:
使用注释代替......
@RunWith(SpringRunner.class)
@SpringBootTest
@EmbeddedKafka(controlledShutdown = true, topics = "foo")
public class So47172973ApplicationTests {
@Autowired
private KafkaTemplate<String, String> template;
@Test
public void test() throws InterruptedException {
template.send("foo", "bar");
Thread.sleep(10_000);
}
}
将代理声明为@Bean
...
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {So47172973ApplicationTests.Config.class, So47172973Application.class})
public class So47172973ApplicationTests {
@Autowired
private KafkaTemplate<String, String> template;
@Test
public void test() throws InterruptedException {
template.send("foo", "bar");
Thread.sleep(10_000);
}
@Configuration
public static class Config {
@Bean
public KafkaEmbedded embeddedKafka() {
return new KafkaEmbedded(1, true, "foo");
}
}
}
答案 2 :(得分:1)
确保在每个集成测试中都同时设置了@SpringBootTest
和@EmbeddedKafka
。
当您同时使用@SpringBootTest
批注运行多个集成测试时,这是一个常见的错误。由于您已经在应用程序配置器Bean中注册了DefaultKafkaConsumerFactory
和DefaultKafkaProducerFactory
,并且可能还在那里使用了@Value("${spring.kafka.bootstrap-servers}")
,因此您有义务在所有称为spring-boot应用程序的地方设置@EmbeddedKafka(partitions = 1, topics = {"topic"})
在测试服务器容器上运行。 @EmbeddedKafka
负责调用EmbeddedKafkaContextCustomizer
,以注册kafka引擎所需的所有环境变量(以及其他spring.embedded.kafka.brokers
)。
在集成测试中没有@EmbeddedKafka
的情况下,spring将在服务器上运行您的应用程序,但是没有机制来设置kafka引擎使用的环境。
答案 3 :(得分:0)
得到了类似的问题,@ taro的答案没有解决我的问题。
我通过从static
对象中移除 EmbeddedKafka
并使用@ClassRule
注释替换 @Rule
来解决此问题。
@Rule
public KafkaEmbedded embeddedKafka = new KafkaEmbedded(1, true, "topic")