使用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
相关产品推荐
相关产品推荐

