Я пытаюсь запустить модульный тест Spring Boot на уровне контроллера с Mock для моей зависимости уровня обслуживания. Однако для этого Mock требуется зависимость от репозитория в нисходящем направлении, которая использует объект EntityManager, что приводит к сбою моего теста при загрузке ApplicationContext.

Мой тест не связан с зависимостью репозитория или EntityManager, он использует объект службы Mocked для возврата готового ответа. Почему Spring жалуется на репо / EntityManager, если я хочу только издеваться над объектом сервисного уровня?

Тестовый код блока контроллера:

@RunWith(SpringRunner.class)
@WebMvcTest
@AutoConfigureWebClient
public class MobileWearControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    UserDeviceService userDeviceService;

    //.....
}

Код UserDeviceService:

@Service
public class UserDeviceService {

    private UserDeviceRepository userDeviceRepository;

    public UserDeviceService(UserDeviceRepository userDeviceRepository) {
        this.userDeviceRepository = userDeviceRepository;
    }

    //....
}

Код UserDeviceRepository:

@Repository
public class UserDeviceRepositoryImpl implements UserDeviceRepositoryCustom {

    @PersistenceContext
    private EntityManager em;

    //....
}

Ожидается тест для запуска.

Фактический результат - следующая трассировка стека:

java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDeviceRepositoryImpl': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available
...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available
...

1
Alan Bentley 17 Апр 2019 в 00:15

2 ответа

Лучший ответ

Моей проблемой были аннотации, которые я использовал для своего теста.

Использование @AutoConfigureWebClient пытается выполнить весь Spring Spring; так как я тестирую модуль моего контроллера, я хочу протестировать только веб-слой и смоделировать нисходящие зависимости (т.е. UserDeviceService). Так что вместо этого я должен использовать @SpringBootTest и @AutoConfigureMockMvc, что установит мой контекст Spring только для уровня контроллера.

Используя этот подход, я могу заставить UserDeviceService успешно выполнять макет и, таким образом, позволить моему тесту скомпилироваться и выполнить:

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

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    UserDeviceService userDeviceService;

    //...
}
1
Alan Bentley 17 Апр 2019 в 13:31

Для начала нужно указать, какие контроллеры вы собираетесь тестировать

@WebMvcTest(YourController.class)

Кроме того, в JUnit5 вам не нужно настраивать какие-либо расширения, поскольку @WebMvcTest содержит @ExtendWith(SpringExtension.class). Вы, очевидно, на JUnit4, но это не должно причинить вреда.

Проверьте, например, https://spring.io/guides/gs/testing-web/

0
Lesiak 17 Апр 2019 в 11:20