You need to enable JavaScript to run this app. Quarkus非全局Mock依赖注入测试报错排查与最优实现方案咨询
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus非全局Mock依赖注入测试报错排查与最优实现方案咨询

问题分析
  • 你在@BeforeEach中手动实例化的DummyReceiver未被Quarkus的CDI容器托管,CDI事件总线分发的DummyMessage只会被容器自动初始化的DummyReceiver实例消费,该容器实例注入的是真实的DummyDependency实现,你自行创建的mock实例不会收到任何调用,因此断言失败。
  • 运行日志中两条DummyReceiver创建记录也验证了该问题:第一条是你手动创建的、绑定了mock的实例,第二条是Quarkus容器启动时初始化的、绑定了真实实现代理的实例。
  • 补充说明:你之前对Quarkus官方Mock机制的理解存在偏差,Quarkus的@Mock/@MockBean是测试类级别隔离的,不同测试类的mock实例完全独立,不会出现所有测试共用同一个mock的情况。
修复方案

方案1:纯单元测试(无需启动Quarkus容器,执行速度最快)

不需要依赖CDI容器能力,直接调用业务方法测试即可:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.concurrent.TimeUnit;

public class DummyReceiverTest {

  private DummyDependencyMock mock;
  private DummyReceiver receiver;

  @BeforeEach
  public void setup() {
    mock = new DummyDependencyMock();
    receiver = new DummyReceiver(mock);
  }

  @Test
  public void test() throws Exception {
    String id = "123";
    // 直接调用业务方法,不走CDI事件分发
    receiver.onProcessScannerMessage(new DummyMessage(id));
    String storedId = mock.ids.poll(1, TimeUnit.SECONDS);
    Assertions.assertEquals("123", storedId);
  }
}

方案2:Quarkus集成测试(使用官方Mock机制,适合需要验证CDI事件等容器特性的场景)

首先引入Quarkus Mockito依赖:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-junit5-mockito</artifactId>
  <scope>test</scope>
</dependency>

改写测试类,使用@MockBean替换容器中的依赖实现:

import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.mockito.MockBean;
import java.util.concurrent.TimeUnit;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

@QuarkusTest
public class DummyReceiverTest {

  @Inject
  Event<DummyMessage> messageEvent;

  // 仅在当前测试类范围内,将容器中DummyDependencyInterface的实现替换为该mock实例
  @MockBean
  DummyDependencyMock mock;

  @Test
  public void test() throws Exception {
    String id = "123";
    messageEvent.fire(new DummyMessage(id));
    String storedId = mock.ids.poll(1, TimeUnit.SECONDS);
    Assertions.assertEquals("123", storedId);
  }
}

方案3:Mockito注解驱动单元测试(和你提供的示例方案逻辑一致)

无需启动Quarkus容器,通过Mockito注解自动注入mock:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.verify;

@ExtendWith(MockitoExtension.class)
public class DummyReceiverTest {

  @Mock
  DummyDependencyInterface dependencyMock;

  @InjectMocks
  DummyReceiver receiver;

  @Test
  public void test() {
    String testId = "123";
    receiver.onProcessScannerMessage(new DummyMessage(testId));
    // 验证依赖方法被调用且参数符合预期
    verify(dependencyMock).store(testId);
  }
}

内容的提问来源于stack exchange,提问作者MikeElmwood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 04:45:03