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

Mockito测试UserService时UserMapper空指针问题求助

解决UserMapper注入为null的问题

问题原因

@InjectMocks只会自动注入被@Mock或@Spy标记的依赖,你的UserMapper既没有被Mockito注解标记,也没有手动注入,所以测试时会出现null。

解决方案

方案1:手动实例化真实UserMapper并构造Service

MapStruct会为UserMapper接口生成对应的实现类(比如UserMapperImpl),你可以直接创建真实的Mapper实例,通过构造函数手动注入到UserServiceImpl中:

@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    private UserServiceImpl userService;
    @Mock
    private UserRepository userRepository;
    // 实例化真实的UserMapper
    private final UserMapper userMapper = UserMapper.INSTANCE; // 如果Mapper定义了INSTANCE常量,否则用new UserMapperImpl()

    @BeforeEach
    void setUp() {
        // 手动构造Service,注入Mock的Repository和真实的Mapper
        userService = new UserServiceImpl(userRepository, userMapper);
    }

    @Test
    public void findById_withValidUserId_returnsUser() {
        Integer userId = 1;
        User expectedUser = User.builder().id(userId).build();
        Mockito.when(userRepository.findById(Mockito.argThat(argument -> argument != null && argument >= 1)))
                .thenReturn(Optional.of(expectedUser));
        UserResponse userResponse = userService.findById(userId);

        Assertions.assertNotNull(userResponse);
        Assertions.assertEquals(expectedUser.getId(), userResponse.id());
    }
}

方案2:使用Spring Boot Test容器管理真实Mapper

如果是Spring Boot项目,可借助Spring容器自动装配真实的UserMapper,同时用@MockBean替换UserRepository为Mock对象:

@SpringBootTest
class UserServiceTest {
    @Autowired
    private UserServiceImpl userService;
    @MockBean
    private UserRepository userRepository;

    @Test
    public void findById_withValidUserId_returnsUser() {
        Integer userId = 1;
        User expectedUser = User.builder().id(userId).build();
        Mockito.when(userRepository.findById(Mockito.argThat(argument -> argument != null && argument >= 1)))
                .thenReturn(Optional.of(expectedUser));
        UserResponse userResponse = userService.findById(userId);

        Assertions.assertNotNull(userResponse);
        Assertions.assertEquals(expectedUser.getId(), userResponse.id());
    }
}

这种方式无需手动处理Mapper实例,但会加载Spring容器,测试启动速度稍慢。

方案3:用@Spy注入真实UserMapper

通过@Spy标记真实的Mapper实例,让Mockito自动注入到Service中:

@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    @InjectMocks
    private UserServiceImpl userService;
    @Mock
    private UserRepository userRepository;
    @Spy
    private final UserMapper userMapper = UserMapper.INSTANCE; // 或new UserMapperImpl()

    @Test
    public void findById_withValidUserId_returnsUser() {
        Integer userId = 1;
        User expectedUser = User.builder().id(userId).build();
        Mockito.when(userRepository.findById(Mockito.argThat(argument -> argument != null && argument >= 1)))
                .thenReturn(Optional.of(expectedUser));
        UserResponse userResponse = userService.findById(userId);

        Assertions.assertNotNull(userResponse);
        Assertions.assertEquals(expectedUser.getId(), userResponse.id());
    }
}

内容的提问来源于stack exchange,提问作者IvanDx

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:05:22