Добавьте еще один компонент в "@WebMvcTest" - PullRequest
1 голос
/ 07 мая 2019

У меня есть контроллер и тест, использующий @WebMvcTest, и он работает нормально. Теперь мне нужно было добавить небольшую логику проверки и для этого я @Autowired дополнительный компонент (@Component, MapstructMapper).

Как и ожидалось, теперь тест не пройден из-за @WebMvcTest. (Компоненты не обнаружены)

Есть ли способ добавить один компонент в созданный контекст?

Поскольку я использую @MockBeans для имитации уровня службы: есть ли способ делегировать все ложные вызовы реальному объекту? С этим я мог бы издеваться над маппером и делегировать настоящему мапперу?!

1 Ответ

2 голосов
/ 09 мая 2019

Простой способ получения дополнительных компонентов в контексте - использование вложенных классов конфигурации в тестовых классах

@TestConfiguration
static class AdditionalConfig {
    @Bean
    public SomeBean getSomeBean() {
        return new SomeBean());
    }
}

Пример:

Сценарий - если у вас есть какой-нибудь контроллер, скажем ProductController , и у вас есть соответствующий слайс-тест для класса, скажем ProductionControllerTest

@RestController
public class ProductController {

    @Autowired
    private IProductService productService;

    @Autowired
    private IProductValidator productValidator;


    @GetMapping("product")
    public Product getProduct(@RequestParam Long id) {

        Product product = productService.getProduct(id); // you are using mockBean of productService

        productValidator.validateProduct(product); // you need real bean of productValidator
        return product;
    }
}

Соответствующий класс слайд-теста с дополнительной конфигурацией компонента

@RunWith(SpringRunner.class)
@WebMvcTest
public class ProductControllerSliceTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private IProductService productService;

    @Autowired
    private ApplicationContext applicationContext;

    @TestConfiguration
    static class AdditionalConfig {
        @Bean
        public IProductValidator productValidator() {
            return new ProductValidator();
        }
    }


    @Test
    public void testProductGetById() throws Exception {
        Product testProductWithID1L = new Product(1L, "testProduct");
        when(productService.getProduct(anyLong())).thenReturn(testProductWithID1L);

        mockMvc.perform(get("/product")
                .param("id", "1")).andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("name")
                        .value("testProduct"))
                .andExpect(MockMvcResultMatchers.jsonPath("id")
                        .value("1"));
    }
}

Дополнительные соображения относительно вашего сценария: Если вы действительно намереваетесь выполнить модульное тестирование класса контроллера, то в идеале вам следует смоделировать все дополнительные зависимости класса, который вы тестируете. В идеале, целью модульного теста является только проверка поведения тестируемого объекта / класса. Все поведение зависимых классов или внешние вызовы должны быть посмешищем.
Когда вы начинаете тестировать несколько классов вместе в рамках одного теста, вы все больше переходите к компонентному тесту или интеграционному тесту

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...