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

如何用JUnit/Mockito测试含数据库加载静态码表的Java类?

无需/低依赖注入的Codes类测试方案

方案1:通过反射直接修改静态CODES集合

利用Java反射API直接替换静态CODES集合的内容,完全不需要修改业务代码,跳过数据库加载逻辑。

示例测试代码:

import org.junit.jupiter.api.BeforeEach;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

class CodesTest {

    @BeforeEach
    void setUp() throws NoSuchFieldException, IllegalAccessException {
        // 获取静态CODES字段
        Field codesField = Codes.class.getDeclaredField("CODES");
        // 取消访问权限检查
        codesField.setAccessible(true);
        // 构造测试用码表数据
        Map<String, String> testCodes = new HashMap<>();
        testCodes.put("001", "测试状态1");
        testCodes.put("002", "测试状态2");
        // 替换静态字段值
        codesField.set(null, testCodes);
    }

    @org.junit.jupiter.api.Test
    void getCodeStr_ShouldReturnCorrectValue() {
        assert Codes.getCodeStr("001").equals("测试状态1");
        assert Codes.getCodeStr("002").equals("测试状态2");
    }
}
  • 优点:零业务代码侵入,无需额外依赖,仅用JUnit原生能力即可实现。
  • 缺点:反射代码对字段名强依赖,若业务类中CODES字段更名,测试代码需同步修改。

方案2:添加测试专用的静态初始化方法

在Codes类中新增一个包级私有或测试可见的静态方法,用于手动注入测试数据,生产环境不会调用该方法。

原Codes类修改(仅新增测试方法):

public class Codes {
    private static Map<String, String> CODES;

    public static void init() {
        // 原数据库加载逻辑
    }

    public static String getCodeStr(String code) {
        return CODES.get(code);
    }

    // 测试专用方法,包级私有,仅同包测试类可调用
    static void setTestCodes(Map<String, String> testCodes) {
        CODES = testCodes;
    }
}

测试类代码:

import org.junit.jupiter.api.BeforeEach;
import java.util.HashMap;
import java.util.Map;

class CodesTest {

    @BeforeEach
    void setUp() {
        Map<String, String> testCodes = new HashMap<>();
        testCodes.put("001", "测试状态1");
        Codes.setTestCodes(testCodes);
    }

    @org.junit.jupiter.api.Test
    void getCodeStr_ShouldReturnCorrectValue() {
        assert Codes.getCodeStr("001").equals("测试状态1");
    }
}
  • 优点:代码直观易维护,比反射写法简洁;仅需对业务类做极小改动,不影响生产逻辑。
  • 缺点:业务类中引入了测试相关代码,虽无功能影响,但属于非业务代码侵入。

方案3:用PowerMock静态Mock跳过数据库加载

若能接受引入少量扩展依赖,可使用PowerMock(Mockito的扩展)mock静态方法和字段,直接跳过数据库加载逻辑并注入测试数据。

首先添加Maven测试依赖:

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
</dependency>

测试类代码:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.HashMap;
import java.util.Map;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Codes.class)
public class CodesTest {

    @Test
    void getCodeStr_ShouldReturnCorrectValue() {
        // 构造测试数据
        Map<String, String> testCodes = new HashMap<>();
        testCodes.put("001", "测试状态1");
        
        // 静态mock Codes类,替换CODES字段
        PowerMockito.field(Codes.class, "CODES").set(null, testCodes);
        
        // 验证查询结果
        assert Codes.getCodeStr("001").equals("测试状态1");
    }
}
  • 优点:可直接mock掉init方法的执行,避免数据库连接尝试;代码比反射更简洁。
  • 缺点:需要引入PowerMock依赖,有一定学习成本;JUnit5需使用对应版本的PowerMock适配包。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 05:55:16