使用@SpyBean 时找不到定义 [SpyDefinition... 的 bean
No bean found for definition [SpyDefinition... when using @SpyBean
我有一个使用 @Component
内部的 @KafkaListener
侦听 Kafka 消息的应用程序。现在我想用 Kafka 测试容器(在后台启动 Kafka)进行集成测试。在我的测试中,我想验证侦听器方法是否已调用并完成,但是当我在测试中使用 @SpyBean
时,我得到:
No bean found for definition [SpyDefinition@7a939c9e name = '', typeToSpy = com.demo.kafka.MessageListener, reset = AFTER]
我正在使用 Kotling,重要 classes:
Class 测试
@Component
class MessageListener(private val someRepository: SomeRepository){
@KafkaListener
fun listen(records: List<ConsumerRecord<String, String>>) {
// do something with someRepository
}
}
基础测试class
@ExtendWith(SpringExtension::class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class KafkaContainerTests {
// some functionality to spin up kafka testcontainer
}
测试class
class MessageListenerTest @Autowired constructor(
private val someRepository: SomeRepository
) : KafkaContainerTests() {
@SpyBean
private lateinit var messageListenerSpy: MessageListener
private var messageListenerLatch = CountDownLatch(1)
@BeforeAll
fun setupLatch() {
logger.debug("setting up latch")
doAnswer {
it.callRealMethod()
messageListenerLatch.count
}.whenever(messageListenerSpy).listen(any())
}
@Test
fun testListener(){
sendKafkaMessage(someValidKafkaMessage)
// assert that the listen method is being called & finished
assertTrue(messageListenerLatch.await(20, TimeUnit.SECONDS))
// and assert someRepository is called
}
}
我感到困惑的原因是,当我将 MessageListener 添加到 MessageListenerTest
的 @Autowired
构造函数时,它确实成功注入了。
为什么使用@SpyBean
时测试找不到bean?
我用 Java 效果很好:
@SpringBootTest
class So58184716ApplicationTests {
@SpyBean
private Listener listener;
@Test
void test(@Autowired KafkaTemplate<String, String> template) throws InterruptedException {
template.send("so58184716", "foo");
CountDownLatch latch = new CountDownLatch(1);
willAnswer(inv -> {
inv.callRealMethod();
latch.countDown();
return null;
}).given(this.listener).listen("foo");
assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue();
verify(this.listener).listen("foo");
}
}
@SpringBootApplication
public class So58184716Application {
public static void main(String[] args) {
SpringApplication.run(So58184716Application.class, args);
}
@Bean
public NewTopic topic() {
return TopicBuilder.name("so58184716").partitions(1).replicas(1).build();
}
}
@Component
class Listener {
@KafkaListener(id = "so58184716", topics = "so58184716")
public void listen(String in) {
System.out.println(in);
}
}
我有一个使用 @Component
内部的 @KafkaListener
侦听 Kafka 消息的应用程序。现在我想用 Kafka 测试容器(在后台启动 Kafka)进行集成测试。在我的测试中,我想验证侦听器方法是否已调用并完成,但是当我在测试中使用 @SpyBean
时,我得到:
No bean found for definition [SpyDefinition@7a939c9e name = '', typeToSpy = com.demo.kafka.MessageListener, reset = AFTER]
我正在使用 Kotling,重要 classes:
Class 测试
@Component
class MessageListener(private val someRepository: SomeRepository){
@KafkaListener
fun listen(records: List<ConsumerRecord<String, String>>) {
// do something with someRepository
}
}
基础测试class
@ExtendWith(SpringExtension::class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class KafkaContainerTests {
// some functionality to spin up kafka testcontainer
}
测试class
class MessageListenerTest @Autowired constructor(
private val someRepository: SomeRepository
) : KafkaContainerTests() {
@SpyBean
private lateinit var messageListenerSpy: MessageListener
private var messageListenerLatch = CountDownLatch(1)
@BeforeAll
fun setupLatch() {
logger.debug("setting up latch")
doAnswer {
it.callRealMethod()
messageListenerLatch.count
}.whenever(messageListenerSpy).listen(any())
}
@Test
fun testListener(){
sendKafkaMessage(someValidKafkaMessage)
// assert that the listen method is being called & finished
assertTrue(messageListenerLatch.await(20, TimeUnit.SECONDS))
// and assert someRepository is called
}
}
我感到困惑的原因是,当我将 MessageListener 添加到 MessageListenerTest
的 @Autowired
构造函数时,它确实成功注入了。
为什么使用@SpyBean
时测试找不到bean?
我用 Java 效果很好:
@SpringBootTest
class So58184716ApplicationTests {
@SpyBean
private Listener listener;
@Test
void test(@Autowired KafkaTemplate<String, String> template) throws InterruptedException {
template.send("so58184716", "foo");
CountDownLatch latch = new CountDownLatch(1);
willAnswer(inv -> {
inv.callRealMethod();
latch.countDown();
return null;
}).given(this.listener).listen("foo");
assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue();
verify(this.listener).listen("foo");
}
}
@SpringBootApplication
public class So58184716Application {
public static void main(String[] args) {
SpringApplication.run(So58184716Application.class, args);
}
@Bean
public NewTopic topic() {
return TopicBuilder.name("so58184716").partitions(1).replicas(1).build();
}
}
@Component
class Listener {
@KafkaListener(id = "so58184716", topics = "so58184716")
public void listen(String in) {
System.out.println(in);
}
}