应用运行正常但单元测试中CustomerMapper返回Null问题求助
嘿,我一眼就看出问题出在哪了——你的单元测试里完全没处理CustomerMapper这个依赖!
问题根源
在应用运行时,Spring(或是你用的依赖注入框架)会帮你实例化CustomerMapper(比如MapStruct这类工具会自动生成实现类并注入到服务中),所以一切功能正常。但单元测试是孤立执行的,不会加载完整的Spring上下文,@InjectMocks只会注入那些被@Mock或@Spy标记的依赖。你的CustomerMapper既没被Mock,也没手动初始化,所以调用它的map方法时自然返回null。
修复步骤
给CustomerMapper添加Mock注解
在测试类中,给CustomerMapper加上@Mock注解,让Mockito为它创建一个Mock实例,这样@InjectMocks就能把它注入到CustomerService里:public class CustomerServiceTest { @Mock private CustomerRepository customerRepository; // 新增这行Mock注解 @Mock private CustomerMapper customerMapper; @InjectMocks private CustomerService customerService; @BeforeEach public void createMocks() { MockitoAnnotations.initMocks(this); } // 测试方法... }Mock Mapper的map方法返回值
在测试方法里,你需要指定当调用customerMapper.map()时应该返回什么CustomerDto对象,这样getById方法才能拿到非空的结果继续执行:@Test public void testCustomerDetails() { Customer expectedCustomer = DummyCustomer.create(); // 先准备好要返回的CustomerDto实例(可以用你自己的dummy方法或者构造器创建) CustomerDto expectedDto = new CustomerDto(); // 或者如果有对应dummy工具类的话:CustomerDto expectedDto = DummyCustomerDto.create(); // Mock Repository的查询返回 when(customerRepository.findCustomerByIdAndIsDeletedFalse(expectedCustomer.getId())) .thenReturn(Optional.of(expectedCustomer)); // 关键:Mock Mapper的map方法,指定传入expectedCustomer时返回expectedDto when(customerMapper.map(expectedCustomer)).thenReturn(expectedDto); Customer response = this.customerService.customerDetails(expectedCustomer.getId()); // 这里可以添加断言验证结果,比如: // assertNotNull(response); // 其他业务逻辑相关的断言... }可选:简化测试配置(Mockito 2.2+)
如果你用的是Mockito 2.2及以上版本,可以用@ExtendWith(MockitoExtension.class)替代MockitoAnnotations.initMocks(this),让测试代码更简洁:@ExtendWith(MockitoExtension.class) public class CustomerServiceTest { @Mock private CustomerRepository customerRepository; @Mock private CustomerMapper customerMapper; @InjectMocks private CustomerService customerService; // 不需要@BeforeEach的initMocks方法了 @Test public void testCustomerDetails() { // 测试逻辑同上 } }
额外提醒
单元测试的核心是孤立验证目标服务的逻辑,所以所有依赖(Repository、Mapper、其他服务)都应该被Mock,并且明确指定它们的返回值,这样才能聚焦测试CustomerService本身的代码是否正确,而不是依赖的实现。
内容的提问来源于stack exchange,提问作者alina

