SpringBoot中Mockito注入服务时无法Mock依赖服务的JUnit测试问题
解决SpringBoot服务测试中Mock失效的问题
这种情况我之前调试服务测试时也碰到过,大概率是Mock对象的注入逻辑或者依赖初始化方式出了问题,咱们一步步排查解决:
1. 先确认Mock框架的注解配置是否正确
如果你用的是Mockito,要确保测试类里的Mock对象能正确注入到被测试的EmployeeService中:
- 对于JUnit 5,测试类要加上
@ExtendWith(MockitoExtension.class)来启用Mockito的扩展支持 - 对
RoleService和GroupService用@Mock标记为Mock对象 - 对
EmployeeService用@InjectMocks标记,让Mockito自动把Mock对象注入进去
举个正确的测试类示例:
@ExtendWith(MockitoExtension.class) public class EmployeeServiceTest { @Mock private RoleService roleService; @Mock private GroupService groupService; @InjectMocks private EmployeeService employeeService; @Test void testCreateEmp() { // 构造测试用的员工对象 Employee testEmp = new Employee(); testEmp.setEmpId("1001"); // 打桩:指定Mock方法的行为(这里模拟无返回值的调用) doNothing().when(roleService).createRole(any(Employee.class)); doNothing().when(groupService).createGroup(any(Employee.class)); // 执行被测试方法 employeeService.createEmp(testEmp); // 验证Mock方法是否被正确调用 verify(roleService, times(1)).createRole(testEmp); verify(groupService, times(1)).createGroup(testEmp); } }
2. 检查被测试服务的依赖注入方式
如果你的EmployeeService里是直接用new关键字创建RoleService或GroupService的实例,那Mock对象根本没法替换掉真实实例,自然会执行真实方法:
❌ 错误写法:
@Service public class EmployeeService { // 直接new实例,Mock无法生效 private RoleService roleService = new RoleServiceImpl(); public void createEmp(Employee emp) { roleService.createRole(emp); // ... } }
✅ 正确写法:用构造器注入(Spring官方推荐)或者@Autowired注入依赖:
@Service public class EmployeeService { private final RoleService roleService; private final GroupService groupService; // 构造器注入,方便测试时替换依赖 public EmployeeService(RoleService roleService, GroupService groupService) { this.roleService = roleService; this.groupService = groupService; } public void createEmp(Employee emp) { roleService.createRole(emp); groupService.createGroup(emp); } }
3. 如果你用了@SpringBootTest,要替换Spring上下文里的Bean
如果你的测试类加载了完整的Spring上下文(比如用了@SpringBootTest),单纯的@Mock注解不会替换掉上下文里的真实Bean,这时候要改用@MockBean来替换:
@SpringBootTest public class EmployeeServiceIntegrationTest { @MockBean private RoleService roleService; @MockBean private GroupService groupService; @Autowired private EmployeeService employeeService; @Test void testCreateEmp() { doNothing().when(roleService).createRole(any(Employee.class)); doNothing().when(groupService).createGroup(any(Employee.class)); employeeService.createEmp(new Employee()); // 验证Mock方法的调用情况 verify(roleService).createRole(any()); } }
@MockBean会自动把Spring上下文中对应的真实服务替换成Mock对象,这样调用时就不会走真实逻辑了。
4. 检查Mock打桩的方法签名是否匹配
如果打桩时用的参数匹配器和实际调用的参数类型不匹配,Mock也会失效。比如createRole接收的是Employee类型,但你打桩时用了anyString(),这时候Mock不会生效,还是会执行真实方法。要确保参数匹配器和实际调用的参数一致,比如用any(Employee.class)或者具体的参数值。
总结
最常见的问题就是依赖初始化方式错误(直接new实例)或者Mock对象没有正确注入到被测试类,按照上面的步骤排查,应该就能解决Mock失效的问题了。
内容的提问来源于stack exchange,提问作者DHR
相关产品推荐
相关产品推荐

