JUnit+MockMvc测试中BDDMockito模拟Service返回值失败求助
问题解答:JUnit测试中用BDDMockito.given()Mock Service方法的可行性及问题修复
当然可以用BDDMockito.given()来设置Controller依赖的Service方法返回值,你的测试失败是因为几个关键细节没处理好,导致Mock的Service方法没有生效,最终返回null引发NPE。下面一步步分析问题并给出修复方案:
核心问题分析
你遇到的NullPointerException是因为:
- MockMvc未正确初始化:你的测试类里声明了
restUserSystemMockMvc但没有赋值,发送请求的环节根本没正确关联到Spring上下文里的Controller,请求无法触达Mock的Service所在的上下文。 - Mock参数匹配不精准:你用测试里的
userSystemDTO作为given()的参数,但Controller接收的是请求体反序列化后的新DTO对象,和测试里的不是同一个实例,导致Mock的匹配条件不满足,Service方法返回默认的null。 - Mock返回的DTO可能存在null属性:如果
createNewUserSystemDTO()返回的UserSystemDTO的id为null,Controller里构建URI时调用result.getId()也会触发NPE。
具体修复步骤
1. 正确初始化MockMvc
有两种方式可以解决这个问题:
- 方式一:直接注入MockMvc
@RunWith(SpringRunner.class) @SpringBootTest(classes = {SecurityBeanOverrideConfiguration.class, AccountApp.class}) public class UserSystemResourceIntTest { @MockBean private UserSystemService userSystemServiceMock; // 直接注入MockMvc @Autowired private MockMvc restUserSystemMockMvc; // ... 其他代码不变 }
- 方式二:在
@Before方法中手动构建
@RunWith(SpringRunner.class) @SpringBootTest(classes = {SecurityBeanOverrideConfiguration.class, AccountApp.class}) public class UserSystemResourceIntTest { @MockBean private UserSystemService userSystemServiceMock; private MockMvc restUserSystemMockMvc; @Autowired private WebApplicationContext webApplicationContext; private UserSystem userSystem; @Before public void initTest() { userSystem = createEntity(em); // 初始化MockMvc restUserSystemMockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); } // ... 其他代码不变 }
2. 修正Mock的参数匹配逻辑
把精准匹配换成宽松匹配,确保任何UserSystemDTO类型的参数都能触发Mock返回值:
// 替换原来的given语句 given(userSystemServiceMock.newAccount(any(UserSystemDTO.class))).willReturn(createNewUserSystemDTO());
注意要导入org.mockito.ArgumentMatchers.any这个静态方法。
3. 确保Mock返回的DTO属性完整
检查createNewUserSystemDTO()方法,确保返回的UserSystemDTO的id不为null,比如给它设置一个有效值:
private static UserSystemDTO createNewUserSystemDTO() { UserSystemDTO newUserSystemDTO = new UserSystemDTO( 1L, // 这里设置一个非null的id值 DEFAULT_NAME, DEFAULT_EMAIL, DEFAULT_PASSWORD, DEFAULT_PHONE, DEFAULT_PHONE, DEFAULT_DOCUMENT_TYPE, DEFAULT_GENDER, DEFAULT_LANG_KEY, null, null, null, null); return newUserSystemDTO; }
验证修复后的流程
完成上述修改后,测试的执行逻辑会变成:
- Spring上下文启动,
@MockBean的userSystemServiceMock替换掉原有的UserSystemService实例 - MockMvc正确初始化,能将请求转发到
UserSystemResource - 发送POST请求时,Controller调用
userSystemServiceMock.newAccount(),因为参数匹配成功,返回你预设的UserSystemDTO - Controller正常构建响应,返回201状态码,测试通过
内容的提问来源于stack exchange,提问作者user2831852
相关产品推荐
相关产品推荐

