Kotlin Quarkus应用Kafka测试阶段遭遇SRMSG18304错误:未知通道dial-out排查求助
解决Quarkus Kafka测试中"Unknown channel dial-out"错误
看起来你在Quarkus集成Kafka的测试中遇到了通道识别问题,我来帮你分析下原因并给出解决方案:
问题诊断
你的错误根源在于模拟对象与真实测试组件的冲突,具体有两个关键点:
- MockK Emitter覆盖了通道配置:你用
@MockK注解了Emitter,这会让MockK生成一个模拟实例,完全替代了Quarkus通过InMemoryConnector创建的真实Emitter。这就导致你的InMemoryConnector配置的dial-out通道根本没有被使用,自然会提示"未知通道"。 - 手动创建InMemoryConnector实例无效:测试类里你自己new了
InMemoryConnector,但Quarkus测试环境中已经有一个由框架管理的、关联了你的application.yml配置的实例,手动创建的实例和它完全无关,无法读取到你的通道配置。
解决方案
1. 修改测试类:移除MockK Emitter,注入框架管理的InMemoryConnector
把测试类里的MockK Emitter去掉,改用依赖注入获取Quarkus已经配置好的InMemoryConnector,这样就能正确关联到你的dial-out通道:
import com.abnamro.ddc.pigeon.domain.core.models.events.ClassificationFinishedEvent import io.quarkus.test.common.QuarkusTestResource import io.quarkus.test.junit.QuarkusTest import io.smallrye.reactive.messaging.providers.connectors.InMemoryConnector import io.smallrye.reactive.messaging.providers.connectors.InMemorySink import org.junit.jupiter.api.Test import javax.inject.Inject @QuarkusTest @QuarkusTestResource(KafkaTestResourceLifecycleManager::class) internal class CaptureCaseCompletedTopicPublisherTest { @Inject lateinit var topicPublisher: CaptureCaseCompletedTopicPublisher // 注入Quarkus管理的InMemoryConnector实例,它已经关联了你的application.yml配置 @Inject lateinit var connector: InMemoryConnector // 可以手动创建事件实例,或者如果有生产者的话也可以注入 private val classificationFinishedEvent = ClassificationFinishedEvent(/* 填充你的事件字段 */) @Test internal fun `A proper ClassificationFinishedEvent should return a successful response`() { // 获取配置好的dial-out通道的Sink val outgoingSink: InMemorySink<ClassificationFinishedEvent> = connector.sink("dial-out") // 调用发送方法 topicPublisher.send(classificationFinishedEvent) // 验证消息是否成功发送到通道 assert(outgoingSink.received().size == 1) assert(outgoingSink.received()[0].payload() == classificationFinishedEvent) } }
2. 确保Publisher类正确绑定通道
检查你的CaptureCaseCompletedTopicPublisher类,必须通过@Channel注解明确指定要使用的通道名称,确保和配置文件里的dial-out一致:
import com.abnamro.ddc.pigeon.domain.core.models.events.ClassificationFinishedEvent import org.eclipse.microprofile.reactive.messaging.Channel import org.eclipse.microprofile.reactive.messaging.Emitter import javax.inject.Inject class CaptureCaseCompletedTopicPublisher { // 必须指定@Channel注解,绑定到dial-out通道 @Inject @Channel("dial-out") lateinit var emitter: Emitter<ClassificationFinishedEvent> fun send(event: ClassificationFinishedEvent) { emitter.send(event) } }
3. 可选:简化生命周期管理器
由于你已经在application.yml的%test环境中配置了smallrye-in-memory连接器,其实你的生命周期管理器可以简化(甚至移除),因为配置已经会自动生效。如果保留的话,确保它的通道名称和配置完全一致即可。
额外排查点
- 检查
application.yml的%test配置是否被正确加载:可以在测试中打印配置值,或者查看Quarkus启动日志中是否有加载测试环境配置的信息。 - 确认所有地方的通道名称完全一致:
dial-out的拼写、大小写在配置文件、@Channel注解、测试代码中必须完全相同,不能有空格或拼写错误。
内容的提问来源于stack exchange,提问作者Ricardo de Vries
相关产品推荐
相关产品推荐

