You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus单元测试:如何解决注入引发的数据库连接问题?

Quarkus单元测试注入Service触发数据库连接失败问题

问题描述

单元测试本无需连接数据库,但注入MerchantService时,Quarkus自动尝试连接数据库,报错:

io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/127.0.0.1:3306

测试类代码:

@QuarkusTest
class MyTestClass {

    @InjectMock
    MerchantRepository merchantRepository;

    @Inject
    MerchantService merchantService; // 问题出在此注入环节

    @Inject
    MerchantMapper merchantMapper; 

    @Test
    void testupdate()  {

        MerchantDTO merchantDTO = new MerchantDTO();
        merchantDTO.setId("id");
        merchantDTO.setSomething2("hello");
        merchantDTO.setSomething3("hello");
        merchantDTO.setSomething4("hello");
        merchantDTO.setSomething5(false);
        
        String id = "id";
        MerchantBO merchant = merchantMapper.toBOFromDTO(merchantDTO);
        MerchantBO fake = null;

        when(merchantRepository.somemethod(merchantDTO.getId())).thenReturn(Uni.createFrom().item(merchant));
        when(merchantRepository.somemethod2(Mockito.any(), Mockito.any())).thenReturn(Uni.createFrom().item(fake));
        when(merchantRepository.somemethod3(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(Uni.createFrom().item(fake));

        assertEquals(merchantDTO, merchantService.update(id, merchantDTO).await().indefinitely());
    }
}

Service类代码:

@ApplicationScoped
public class MerchantService {

    @Inject
    MerchantRepository merchantRepository;

    @Inject
    MerchantMapper merchantMapper;

    ...
}

解决方案

方案1:纯单元测试(不启动Quarkus容器)

直接手动实例化Service并注入Mock依赖,完全避开Quarkus容器的初始化逻辑,从根源上杜绝数据库连接尝试:

class MyTestClass {

    private MerchantRepository merchantRepository = Mockito.mock(MerchantRepository.class);
    // 如果MerchantMapper是纯DTO/BO转换类,可直接用真实实例,无需Mock
    private MerchantMapper merchantMapper = new MerchantMapperImpl(); 
    private MerchantService merchantService = new MerchantService();

    @BeforeEach
    void setup() {
        // 手动注入Service的依赖
        merchantService.merchantRepository = merchantRepository;
        merchantService.merchantMapper = merchantMapper;
    }

    @Test
    void testupdate()  {
        MerchantDTO merchantDTO = new MerchantDTO();
        merchantDTO.setId("id");
        merchantDTO.setSomething2("hello");
        merchantDTO.setSomething3("hello");
        merchantDTO.setSomething4("hello");
        merchantDTO.setSomething5(false);
        
        String id = "id";
        MerchantBO merchant = merchantMapper.toBOFromDTO(merchantDTO);
        MerchantBO fake = null;

        when(merchantRepository.somemethod(merchantDTO.getId())).thenReturn(Uni.createFrom().item(merchant));
        when(merchantRepository.somemethod2(Mockito.any(), Mockito.any())).thenReturn(Uni.createFrom().item(fake));
        when(merchantRepository.somemethod3(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(Uni.createFrom().item(fake));

        assertEquals(merchantDTO, merchantService.update(id, merchantDTO).await().indefinitely());
    }
}

方案2:保留@QuarkusTest,禁用数据库相关扩展

如果必须使用@QuarkusTest(比如需要Quarkus上下文支持),在测试配置中禁用数据库扩展或配置无操作数据源:

在src/test/resources/application.properties添加:

# 禁用JDBC数据源
quarkus.datasource.jdbc=false
quarkus.datasource.db-kind=none
# 禁用Hibernate ORM(如果使用了)
quarkus.hibernate-orm.active=false
# 启用Panache Mock(如果Repository是PanacheRepository)
quarkus.panache.mock-active=true

配置后,Quarkus启动时不会尝试初始化数据库连接,同时@InjectMock会正确替换真实的Repository Bean。

方案3:检查Repository的初始化逻辑

如果Repository带有@PostConstruct等初始化方法,即使被Mock,Quarkus可能仍会执行真实Bean的初始化逻辑。此时可以跳过这些方法:

@QuarkusTest
class MyTestClass {

    @InjectMock
    MerchantRepository merchantRepository;

    @Inject
    MerchantService merchantService;

    @Inject
    MerchantMapper merchantMapper; 

    @BeforeEach
    void setup() {
        // 跳过Repository的初始化方法(假设方法名为init)
        Mockito.doNothing().when(merchantRepository).init();
    }

    // 测试方法不变
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 23:20:37