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

使用Mockito.mockConstruction测试时被测类Logger为null如何解决

问题根因

你遇到的问题由两个核心错误导致:

  1. 静态变量初始化时机问题:Utility类的log是静态成员,会在类第一次被加载时就完成初始化,早于你测试方法内的Mock逻辑执行,此时如果LoggerBean初始化失败,log就已经被赋值为null,后续再Mock也不会重新触发静态变量初始化。
  2. Mock逻辑不匹配:
    • 你只Mock了LoggerBean的构造方法,但Utility中是通过静态方法LoggerBean.getLoggerBean()获取LoggerBean实例,你并没有Mock这个静态方法的返回值,所以根本不会用到你Mock的构造生成的对象。
    • 你StubgetLogger方法时传入的参数是测试类UtilityTest.class,但Utility里调用getLogger传入的是Utility.class,Stub规则不匹配,自然返回默认的null。

解决方案

推荐两种可行方案,按需选择:

方案1:直接反射修改静态log字段(最简便)

不需要复杂的Mock逻辑,直接通过反射给Utility的静态log字段赋值即可:

import java.lang.reflect.Field;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;

class UtilityTest {
    @BeforeEach
    void initLog() throws NoSuchFieldException, IllegalAccessException {
        Logger testLog = Logger.getLogger(Utility.class);
        Field logField = Utility.class.getDeclaredField("log");
        logField.setAccessible(true);
        // 静态字段赋值时第一个参数传null即可
        logField.set(null, testLog);
    }

    @Test
    void testFromJson() throws Exception {
        String json = " {\"key\":\"k1\",\"value\":\"v1\"}";
        assertNotNull(Utility.fromJson(json, Tuple.class));
    }
}

方案2:完整Mock静态方法+控制类加载顺序

如果需要严格走LoggerBean的获取流程,可以MockLoggerBean的静态工厂方法,且保证Mock逻辑在Utility类加载前执行:

import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertNotNull;

class UtilityTest {
    @Test
    void testFromJson() throws Exception {
        // 先Mock LoggerBean的静态方法,此时需要保证Utility还未被加载
        try (MockedStatic<LoggerBean> mockedStatic = mockStatic(LoggerBean.class)) {
            // 构造Mock的LoggerBean实例
            LoggerBean mockBean = mock(LoggerBean.class);
            // 注意Stub参数要和Utility里调用的一致,使用Utility.class
            when(mockBean.getLogger(Utility.class)).thenReturn(Logger.getLogger(Utility.class));
            // Stub静态工厂方法的返回值
            mockedStatic.when(LoggerBean::getLoggerBean).thenReturn(mockBean);
            
            // 此时第一次加载Utility类,触发静态变量初始化,会拿到Mock的log实例
            String json = " {\"key\":\"k1\",\"value\":\"v1\"}";
            assertNotNull(Utility.fromJson(json, Tuple.class));
        }
    }
}

如果你的测试运行环境中Utility类已经在测试执行前被加载过,方案2需要配合反射重置log字段才能生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 02:42:02