You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

应用运行正常但单元测试中CustomerMapper返回Null问题求助

解决方案:单元测试中Mapper返回Null的问题

嘿,我一眼就看出问题出在哪了——你的单元测试里完全没处理CustomerMapper这个依赖!

问题根源

在应用运行时,Spring(或是你用的依赖注入框架)会帮你实例化CustomerMapper(比如MapStruct这类工具会自动生成实现类并注入到服务中),所以一切功能正常。但单元测试是孤立执行的,不会加载完整的Spring上下文,@InjectMocks只会注入那些被@Mock或@Spy标记的依赖。你的CustomerMapper既没被Mock,也没手动初始化,所以调用它的map方法时自然返回null。

修复步骤

  1. 给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);
        }
    
        // 测试方法...
    }
    
  2. 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);
        // 其他业务逻辑相关的断言...
    }
    
  3. 可选:简化测试配置(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 22:42:29