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

使用Mockito进行Service测试时出现NullPointerException问题排查

解决测试中CategoryRepository注入空指针问题

测试类尝试用@MockBean创建CategoryRepository实例并注入到CategoryServiceImpl,但运行时抛出空指针异常,提示categoryRepository为null。

测试类代码

@ExtendWith(MockitoExtension.class)
@ExtendWith(SpringExtension.class)
public class CategoryServiceTest {

    @MockBean
    private CategoryRepository categoryRepository;

    @InjectMocks
    private CategoryServiceImpl categoryService;


    @Test
    public void testCheckUniqueInNewModeReturnDuplicateName() {
        Long categoryId = null;
        String name = "Computers";
        String alias = "abc";

        Category category = new Category(categoryId, name, alias);

        Mockito.when(categoryRepository.findByName(name)).thenReturn(category);

        String result = categoryService.checkUnique(categoryId, name, alias);

        assertThat(result).isEqualTo("DuplicateName");
    }
}

异常信息

java.lang.NullPointerException: Cannot invoke "com.marketcruiser.admin.category.CategoryRepository.findByName(String)" because "this.categoryRepository" is null

    at com.marketcruiser.admin.category.CategoryServiceImpl.checkUnique(CategoryServiceImpl.java:136)

服务类代码

@Service
public class CategoryServiceImpl implements CategoryService{

    private final CategoryRepository categoryRepository;


    @Autowired
    public CategoryServiceImpl(CategoryRepository categoryRepository) {
        this.categoryRepository = categoryRepository;
    }

    @Override
    public String checkUnique(Long categoryId, String name, String alias) {
        boolean isCreatingNew = (categoryId == null || categoryId == 0);

        Category categoryByName = categoryRepository.findByName(name);

        if (isCreatingNew) {
            if (categoryByName != null) {
                return "DuplicateName";
            }
        }

        return "OK";
    }
}

错误原因

你同时混用了Mockito的依赖注入机制和Spring的测试机制:

  • @MockBean是Spring提供的注解,用于在Spring测试容器中替换或添加Mock Bean;
  • @InjectMocks是Mockito提供的注解,用于手动将Mock对象注入到目标实例中;
  • 同时添加MockitoExtension和SpringExtension会导致两者的注入逻辑冲突,Spring容器管理的categoryRepository没有被正确注入到@InjectMocks创建的categoryService实例中。

解决方案

方案1:纯Mockito测试(无需Spring容器)

去掉Spring相关注解,仅用Mockito的注解完成依赖注入:

@ExtendWith(MockitoExtension.class)
public class CategoryServiceTest {

    // 用Mockito的@Mock替代Spring的@MockBean
    @Mock
    private CategoryRepository categoryRepository;

    @InjectMocks
    private CategoryServiceImpl categoryService;

    @Test
    public void testCheckUniqueInNewModeReturnDuplicateName() {
        Long categoryId = null;
        String name = "Computers";
        String alias = "abc";

        Category category = new Category(categoryId, name, alias);

        Mockito.when(categoryRepository.findByName(name)).thenReturn(category);

        String result = categoryService.checkUnique(categoryId, name, alias);

        assertThat(result).isEqualTo("DuplicateName");
    }
}

方案2:基于Spring容器的测试

如果测试需要Spring容器支持(比如涉及其他Spring Bean),改用Spring的注入方式:

@ExtendWith(SpringExtension.class)
public class CategoryServiceTest {

    @MockBean
    private CategoryRepository categoryRepository;

    // 用@Autowired让Spring注入容器中的service实例
    @Autowired
    private CategoryServiceImpl categoryService;

    @Test
    public void testCheckUniqueInNewModeReturnDuplicateName() {
        Long categoryId = null;
        String name = "Computers";
        String alias = "abc";

        Category category = new Category(categoryId, name, alias);

        Mockito.when(categoryRepository.findByName(name)).thenReturn(category);

        String result = categoryService.checkUnique(categoryId, name, alias);

        assertThat(result).isEqualTo("DuplicateName");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 13:01:25