В приложении Spring Boot у меня есть два POJO, Foo
и Bar
, и BarToFooConverter
, который выглядит так:
@Component
public class BarToFooConverter implements Converter<Bar, Foo> {
@Override
public Foo convert(Bar bar) {
return new Foo(bar.getBar());
}
}
У меня также есть контроллер, который использует преобразователь:
@RestController("test")
public class TestController {
@Autowired
private ConversionService conversionService;
@RequestMapping(method = RequestMethod.PUT)
@ResponseBody
public Foo put(@RequestBody Bar bar) {
return conversionService.convert(bar, Foo.class);
}
}
Я хотел бы протестировать этот контроллер с помощью @WebMvcTest
, что-то вроде:
@WebMvcTest
@RunWith(SpringRunner.class)
public class TestControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void test() throws Exception {
mockMvc.perform(
put("/test")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"bar\":\"test\"}"))
.andExpect(status().isOk());
}
}
но когда я запускаю это, я обнаруживаю, что мой BarToFooConverter
не был зарегистрирован с ConversionService
:
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [com.example.demo.web.Bar] to type [com.example.demo.web.Foo]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:324)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:206)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:187)
at com.example.demo.web.TestController.put(TestController.java:15)
Кажется, это имеет смысл, потому что, согласно Javadoc:
Использование этой аннотации отключит полную автоматическую настройку и вместо этого применит только конфигурацию, относящуюся к тестам MVC (например, @Controller, @ControllerAdvice, @JsonComponent Filter, WebMvcConfigurer и HandlerMethodArgumentResolver bean-компоненты, но не @Component, @Service или @Repository bean-компоненты).
Однако справочное руководство немного отличается, говоря, что @WebMvcTest
включает Converter
s:
@WebMvcTest автоматически настраивает инфраструктуру Spring MVC и ограничивает сканируемые bean-компоненты @Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, Filter, WebMvcConfigurer и HandlerMethodArgumentResolver. Обычные bean-компоненты @Component не сканируются при использовании этой аннотации.
Похоже тут справочник неверный - или я свой Converter
неправильно прописываю?
Я также пытался издеваться над ConversionService
в своем тесте с помощью:
@WebMvcTest
@RunWith(SpringRunner.class)
public class TestControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ConversionService conversionService;
@Test
public void test() throws Exception {
when(conversionService.convert(any(Bar.class), eq(Foo.class))).thenReturn(new Foo("test"));
mockMvc.perform(
put("/test")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"bar\":\"test\"}"))
.andExpect(status().isOk());
}
}
но теперь Spring жалуется, что мой макет ConversionService
переопределяет значение по умолчанию:
Caused by: java.lang.IllegalStateException: @Bean method WebMvcConfigurationSupport.mvcConversionService called as a bean reference for type [org.springframework.format.support.FormattingConversionService] but overridden by non-compatible bean instance of type [org.springframework.core.convert.ConversionService$$EnhancerByMockitoWithCGLIB$$da4e303a]. Overriding bean of same name declared in: null
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.obtainBeanInstanceFromFactory(ConfigurationClassEnhancer.java:402)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:361)
...
В идеале я хотел бы использовать свой оригинальный подход с настоящим конвертером в моем тесте, а не издеваться над ConversionService
, но с @WebMvcTest
, чтобы ограничить объем запускаемых компонентов, поэтому я также попытался использовать includeFilter
в аннотации @WebMvcTest
:
@WebMvcTest(includeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.example.demo.web.Bar*"))
но он по-прежнему не работает с исходным сообщением об ошибке «Не найден конвертер, способный конвертировать ...».
Это похоже на то, что должно быть довольно распространенным требованием - что мне не хватает?
ConversionService
сейчас вводилось, хотя раньше этого не было. - person DaveyDaveDave   schedule 19.10.2018