Mockito静态方法Mock失效引发空指针异常,求排查思路
核心原因:MockedStatic生命周期过短
你在@PostConstruct方法中使用try-with-resources创建MockedStatic<JwtUtil>,这个资源会在post()方法执行完毕后自动关闭。而集成测试的实际测试代码是在@PostConstruct之后运行的,此时静态方法的Mock已经失效,调用JwtUtil.findSubject()时会执行真实方法,进而因为真实逻辑里的强转或空值导致空指针异常。
解决步骤
延长MockedStatic的生命周期
将MockedStatic作为测试类的成员变量,在测试方法执行前初始化,执行后关闭,确保Mock在整个测试过程中生效:@SpringBootTest @Testcontainers public abstract class AbstractIntegrationTest { private MockedStatic<JwtUtil> jwtUtilMock; private final Faker faker = new Faker(); @BeforeEach void setUp() { // 初始化静态Mock jwtUtilMock = Mockito.mockStatic(JwtUtil.class); // 定义Mock行为 jwtUtilMock.when(() -> JwtUtil.findSubject(any(Principal.class))) .thenReturn(faker.rickAndMorty().character()); } @AfterEach void tearDown() { // 关闭Mock,释放资源 if (jwtUtilMock != null) { jwtUtilMock.close(); } } // 其他测试代码... }验证参数匹配器的正确性
确保使用的是Mockito的ArgumentMatchers.any()(导入org.mockito.ArgumentMatchers),而非其他类的匹配器。如果实际传入的Principal是JwtAuthenticationToken的实例,也可以用any(JwtAuthenticationToken.class)来更精准匹配,但any(Principal.class)本身是合法的,因为JwtAuthenticationToken实现了Principal接口。确认Mock生效状态
在测试方法中先手动调用一次JwtUtil.findSubject(mock(Principal.class)),查看是否返回预期的随机字符,以此验证Mock是否正确生效。如果此时能返回预期值,说明生命周期的问题已经解决。排查真实方法的潜在风险
若Mock生效后仍有异常,需检查测试中传入的Principal是否为null。虽然Mock会覆盖真实方法,但如果代码中其他地方直接操作Principal实例(而非调用findSubject),仍可能导致空指针,这时候需要确保测试中传入的Principal是有效的Mock实例。
内容的提问来源于stack exchange,提问作者JPG

