Mockito抛出空指针异常:Mock仓库未关联至目标类问题排查
我一眼就看出问题出在哪了——你手动创建了PizzaValidator实例,导致Spring的依赖注入根本没生效!
问题根源
虽然你用@MockBean正确创建了IngredientRepository和PizzaSizeRepository的Mock对象,但在setUp()方法里,你又手动new了一个PizzaValidator:
validator = new PizzaValidator();
这个手动创建的实例完全不受Spring管理,它里面的@Autowired字段(那两个仓库)根本不会被注入,所以调用validator.validate()时,这两个仓库都是null,自然抛出NullPointerException。
解决方案
1. 让Spring注入PizzaValidator实例
删掉测试类里手动创建validator的代码,改用@Autowired让Spring给你注入实例:
- 把测试类里的
private PizzaValidator validator = new PizzaValidator();改成@Autowired private PizzaValidator validator; - 删掉
setUp()里的validator = new PizzaValidator();语句
2. 启用Spring测试上下文
确保你的测试类上加上@SpringBootTest注解(或者适合你场景的Spring测试注解,比如@WebMvcTest),因为@MockBean只有在Spring测试上下文里才能生效,把Mock对象注入到Spring管理的Bean中。
3. 修复测试数据的空指针隐患
另外,你的meatPizza对象的sizeDesc和ingredients如果是null的话,调用pizza.getSizeDesc().getId()或者遍历pizza.getIngredients()时也会抛出NPE,所以要在setUp()里给这些字段初始化。
修改后的完整测试类代码
@SpringBootTest public class PizzaValidatorTest { private Pizza meatPizza; @Autowired private PizzaValidator validator; @MockBean private IngredientRepository ingredientRepository; @MockBean private PizzaSizeRepository pizzaSizeRepository; @Before public void setUp() throws Exception { meatPizza = new Pizza(); // 初始化sizeDesc和ingredients,避免调用get方法时NPE meatPizza.setSizeDesc(new PizzaSize()); meatPizza.setIngredients(new ArrayList<>()); } @Test public void validateValid() { when(ingredientRepository.existsById(any())).thenReturn(true); when(pizzaSizeRepository.existsById(any())).thenReturn(true); assertTrue(validator.validate(meatPizza)); } }
额外说明
如果你的测试不需要完整的Spring Boot上下文,也可以用@ExtendWith(SpringExtension.class)替代@SpringBootTest,但@SpringBootTest已经包含了这个扩展,用起来更省心。
内容的提问来源于stack exchange,提问作者baron.jos

