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

Mockito @Mock与@InjectMocks为空:Maven测试失败IDE成功排查

解决Mockito测试中本地Maven/CI构建空指针异常(IntelliJ测试正常)

问题背景

测试目标服务代码:

import org.springframework.stereotype.Service;

import java.time.LocalDate;
import com.dummy.domain.dummy.dao.MatchDAO;

@Service
public class TeamService {

    private MatchDAO matchDAO;

    public TeamService(MatchDAO matchDAO) {
        this.matchDAO = matchDAO;
    }

    public Team get(int teamId) {
        return get(teamId, LocalDate.now());
    }

    public Team get(int teamId, LocalDate date) {
        matchDAO.findMatchIdsForTeam(teamId, date);
        ...
    }
}

对应的测试代码:

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 java.time.LocalDate;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class TeamServiceTest {
    @Mock
    MatchDAO matchDAO;

    @InjectMocks
    TeamService teamService;

//    @BeforeAll
//    public void createMocks() {
//        MockitoAnnotations.initMocks(this);
//    }

    @Test
    public void testGetTeam() {
        when(matchDAO.findMatchIdsForTeam(anyInt(), any(LocalDate.class))).thenReturn(new int[]{1234, 5678});

        Team team = teamService.get(1);
        ... assertions
    }
}

遇到的核心问题:

  • 本地Maven构建和CI流水线运行测试时,频繁触发两类空指针异常:
    1. this.teamService为空,无法调用get方法
    2. matchDAO为空,无法调用findMatchIdsForTeam方法
  • IntelliJ IDE内运行测试完全正常,且已确认本地与CI环境的JDK、Maven版本一致。
  • 已尝试启用/禁用@BeforeAll/@BeforeEach初始化Mock、替换为SpringExtension等方案,问题未解决。

可能的原因与解决办法

1. 校验Mockito与JUnit Jupiter依赖版本兼容性

Mockito和JUnit Jupiter版本不匹配会导致@Mock/@InjectMocks等注解无法被正确解析,这是IDE与Maven构建行为不一致的常见诱因。

解决步骤:

  • 确保mockito-core、mockito-junit-jupiter与junit-jupiter-api/junit-jupiter-engine版本匹配,例如使用Mockito 4.x+搭配JUnit Jupiter 5.8.x+:
<!-- JUnit Jupiter依赖 -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.9.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.9.2</version>
    <scope>test</scope>
</dependency>

<!-- Mockito依赖 -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>4.11.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>4.11.0</version>
    <scope>test</scope>
</dependency>
  • 检查父pom的依赖版本管理,确保子模块继承的版本是兼容的。

2. 排查Maven Surefire插件配置

Maven Surefire插件的配置问题可能导致测试类的注解处理器未被正确加载,进而Mock对象初始化失败。

解决步骤:

  • 确保maven-surefire-plugin版本足够新(建议3.0.0-M7+),并添加如下配置:
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.1.2</version>
            <configuration>
                <useSystemClassLoader>false</useSystemClassLoader>
                <useManifestOnlyJar>false</useManifestOnlyJar>
            </configuration>
        </plugin>
    </plugins>
</build>
  • 执行mvn test -X查看详细日志,确认Mockito扩展是否被正常加载。

3. 检查类的访问权限与模块规则

Mockito通过反射注入Mock对象,若服务类的构造方法、字段访问权限不足,或Java模块系统限制了反射访问,会导致注入失败。

解决步骤:

  • 确保TeamService的构造方法为public(当前代码已满足,但需确认父类或模块访问规则)。
  • 若使用Java模块系统(存在module-info.java),需在主模块中添加opens声明,允许Mockito反射访问:
module your.main.module {
    opens com.your.package to org.mockito.core;
}

4. 统一Mock初始化方式

避免混合使用多种Mockito初始化逻辑,防止出现冲突。

解决步骤:

  • 完全依赖@ExtendWith(MockitoExtension.class),删除所有手动初始化Mock的代码(包括注释的MockitoAnnotations.initMocks(this))。
  • 若必须手动初始化,移除@ExtendWith注解,改用@BeforeEach调用最新的openMocks方法:
@BeforeEach
public void setup() {
    MockitoAnnotations.openMocks(this);
}

5. 消除IDE与Maven的编译差异

IntelliJ可能使用自定义编译器,而Maven使用javac,编译级别或注解处理器差异会导致字节码不一致。

解决步骤:

  • 在pom.xml中明确指定Java版本,与IDE配置保持一致:
<properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
</properties>
  • 执行mvn clean test,清理Maven缓存的旧编译文件后重新构建测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 12:30:52