JUnit5中Mockito模拟HATEOAS场景时Method空指针异常解决
解决StaticPathLinkBuilder单元测试空指针异常的正确Mock方式
问题根源在于你用@Spy处理静态工具类StaticPathLinkBuilder的方式不对——@Spy仅适用于实例对象的部分Mock,无法覆盖静态方法的行为,导致实际执行时还是走了原方法的逻辑,而原方法内部的method参数未被正确初始化,最终抛出空指针异常。
正确的做法是使用Mockito的静态Mock能力来处理静态方法,具体步骤如下:
1. 依赖版本要求
确保你的Mockito版本在3.4.0及以上,这个版本引入了mockStatic方法,支持通过try-with-resources自动管理静态Mock的生命周期,避免影响其他测试用例。
2. 静态Mock StaticPathLinkBuilder
在测试方法中,用mockStatic创建StaticPathLinkBuilder的静态Mock,同时Mock它返回的LinkBuilder对象,提前Stub好createRelativeUri的行为:
import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import static org.mockito.Mockito.*; class YourTargetTest { @Test void testSuccessfully() { // 1. Mock LinkBuilder,模拟createRelativeUri的返回值 LinkBuilder mockLinkBuilder = mock(LinkBuilder.class); when(mockLinkBuilder.createRelativeUri(anyString())) .thenReturn("/mock/relative/uri"); // 替换为你需要的测试用URI // 2. 静态Mock StaticPathLinkBuilder,Stub linkTo方法 try (MockedStatic<StaticPathLinkBuilder> mockedStatic = mockStatic(StaticPathLinkBuilder.class)) { // 根据你实际调用的linkTo重载方法,调整参数匹配器 mockedStatic.when(() -> StaticPathLinkBuilder.linkTo(any(), any())) .thenReturn(mockLinkBuilder); // 3. 执行被测试的方法 YourService service = new YourService(); Object response = service.methodUnderTest(); // 4. 执行断言逻辑 // 例如:assertEquals(expectedUri, response.getLinkUri()); } } }
3. 关键注意事项
- 匹配正确的
linkTo重载:如果你的业务代码调用的是linkTo的其他重载(比如linkTo(Class<?> controllerClass)),需要调整when中的参数匹配器,确保Stub的是实际被调用的方法。 - 避免静态Mock泄漏:必须用try-with-resources包裹
mockStatic,确保测试结束后自动清除静态Mock,防止其他测试用例受到影响。 - 不要混用实例Mock和静态Mock:
StaticPathLinkBuilder是纯静态工具类,不需要也不能用@Spy或@Mock注解处理,必须用静态Mock方式。
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

