Почему компонент не инициализируется при использовании аннотации @MockBean в модульном тестировании

#java #spring #spring-boot #mocking #spring-test

#java #весна #весенняя загрузка #издевательство #spring-test

Вопрос:

У меня очень плохая реализация компонента

 @Component
public class Repository{
    public List<String> people= new ArrayList<>();
  

И у меня также есть тест, в котором я заменяю репозиторий макетом.
Но когда я пытаюсь получить доступ к полю «люди» в тесте через макет репозитория, я получаю исключение NullPointerException

 @RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class MainControllerTest{

    @Autowired
    private MockMvc mockMvc;
        
    @MockBean
    private Repository repository;
           
    @Test
    public void someTest(){
        repository.people // null -> NullPointerException
    }
}
  

Почему это происходит? Инициализирован ли компонент изначально или нет? Каково правильное решение при такой плохой реализации?

Ответ №1:

Компонент инициализируется так, как он должен быть @MockBean . Для вас создается только заглушка. Все вложенные элементы Repository класса игнорируются. В вашем случае у вас есть полностью инициализированный макет. Но, конечно, вложенные поля имеют значение null. Потому что это макет, и вложенные поля не будут инициализированы. Mock предполагает, что вам просто нужна какая-то оболочка этого конкретного класса, чтобы имитировать какое-то поведение.

Что вам нужно сделать, так это перейти @MockBean на @SpyBean . В этом случае поля вашего класса будут инициализированы так, как они определены в вашем Repository классе. Итак, у вас будет реальный Repository объект, но завернутый с помощью Mockito Spy. И это позволит вам выполнять все необходимые манипуляции с этим объектом.