[英]ConversionService not working in Unit Test (spring 3.2)
我擁有一個運行良好的Web應用程序。 現在,我正在嘗試為此編寫單元測試。 我的Web應用程序具有以下conversionService
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="....Class1ToStringConverter"/>
<bean class="....StringToClass1Converter"/>
</list>
</property>
</bean>
<mvc:annotation-driven conversion-service="conversionService" />
哪個很好,當我請求
/somepath/{class1-object-string-representation}/xx
一切都按預期工作(字符串被解釋為Class1對象)。
我的問題是嘗試向控制器編寫單元測試。 只是不使用conversionService而spring只是告訴我
Cannot convert value of type [java.lang.String] to required type [Class1]: no matching editors or conversion strategy found
到目前為止,我的測試:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/applicationContext.xml", "file:src/main/webapp/WEB-INF/jpm-servlet.xml"})
@WebAppConfiguration()
public class GeneralTest {
@Autowired
private WebApplicationContext ctx;
private MockMvc mockMvc;
private TestDAO testDAO = org.mockito.Mockito.mock(TestDAO.class);
@Before
public void setUp() throws Exception {
Mockito.reset(testDAO);
mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
}
@Test
public void testList() throws Exception {
final Test first = new Test(1L, "Hi", 10, new Date(), true);
final Test second = new Test(2L, "Bye", 50, new Date(), false);
first.setTest(second);
when(testDAO.list()).thenReturn(Arrays.asList(first, second));
mockMvc.perform(get("/jpm/class1-id1"))
.andExpect(status().isOk())
.andExpect(view().name("list"))
.andExpect(forwardedUrl("/WEB-INF/jsp/list.jsp"));
}
我缺少什么? 謝謝
像這樣的模擬轉換器
GenericConversionService conversionService = new GenericConversionService();
conversionService.addConverter(new StringToClass1Converter());
Deencapsulation.setField(FIXTURE, conversionService);
我遇到過同樣的問題。 如果要測試單個控制器,則可以嘗試以下操作:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/applicationContext.xml", "file:src/main/webapp/WEB-INF/jpm-servlet.xml"})
@WebAppConfiguration()
public class GeneralTest {
@Autowired
private WebApplicationContext ctx;
@Autowired
private FormattingConversionServiceFactoryBean conversionService;
private MockMvc mockMvc;
@Mock
private TestDAO testDAO;
/* The following assumes you are injecting your DAO into your controller
* If you are using a service layer (most likely), you should
* inject your DAO into your service and your service into your controller.
*/
@InjectMocks
private YourControllerClass controllerToTest;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
//get the conversion service from the factory bean
FormattingConversionService cs = conversionService.getObject();
Mockito.reset(testDAO);
//setup MockMvc using the conversion service
mockMvc = MockMvcBuilders.standaloneSetup(controllerToTest)
.setConversionService(cs)
.build();
}
@Test
public void testList() throws Exception {
final Test first = new Test(1L, "Hi", 10, new Date(), true);
final Test second = new Test(2L, "Bye", 50, new Date(), false);
first.setTest(second);
when(testDAO.list()).thenReturn(Arrays.asList(first, second));
mockMvc.perform(get("/jpm/class1-id1"))
.andExpect(status().isOk())
.andExpect(view().name("list"))
.andExpect(forwardedUrl("/WEB-INF/jsp/list.jsp"));
}
希望有幫助!
我意識到這是一個舊線程,但是像我一樣,在花了幾個小時對為什么不調用其自定義轉換器進行故障排除之后,將來還會有其他人遇到這個問題。
@Mariano D'Ascanio提出的解決方案在沒有控制器(至少沒有您編寫的控制器)的情況下是不夠的,例如當您使用Spring JPA時。 MockMvcBuilders.standaloneSetup
至少需要將一個控制器傳遞給構造函數,因此您不能在這種情況下使用它。 解決該問題的方法是注入org.springframework.core.convert.converter.ConverterRegistry
或更好的方法,它是org.springframework.core.convert.converter.FormatterRegistry
的子類,然后在@PostContruct
方法中注冊您的自定義轉換器/ formatter如下所示:
@PostConstruct
void init() {
formatterRegistry.removeConvertible(String.class, OffsetDateTime.class);
formatterRegistry.addFormatter(customOffsetDateTimeFormatter);
formatterRegistry.addConverter(customOffsetDateTimeConverter);
}
訣竅是使用名稱而不是類型注入ConverterRegistry
,因為對於Web測試,有兩個轉換器注冊表,默認注冊表和mvc。 春季測試使用默認轉換器,所以這就是您需要的轉換器。
// GOTCHA ALERT: There's also a mvcConversionService; tests DO NOT use that
@Resource(name = "defaultConversionService")
private FormatterRegistry formatterRegistry;
希望這可以幫助。
搜索此問題時,此帖子有些過時,但仍是Google的第一批搜索結果之一。
因此,這里是Spring Framework 5的更新。
當您確實配置了Spring文檔中記錄的WebMvc上下文時,您將編寫如下內容:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
// ...
}
}
但是,這未在JUnit上下文中加載! 上帝知道為什么。 但是您需要這樣聲明您的配置類:
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
@Override
public void addFormatters(FormatterRegistry registry) {
// ...
}
}
因此,請刪除@EnableWebMvc
批注並從另一個類中進行擴展,如上所述。 您可能不必更改其他任何內容。 然后,在單元測試中也會調用addFormatters
方法。
這是非常直覺和奇怪的。 但這是真的。 您可以調試帶有斷點的彈簧測試源代碼,然后看到調用了WebMvcConfigurer
接口的所有其他方法,但沒有調用addFormatters
。 也許他們只是忘了稱呼它,或者他們還有其他“原因”。 通過從WebMvcConfigurationSupport
擴展,可以WebMvcConfigurationSupport
每個方法,並且JUnit測試成功。
特別是,此代碼最終將被執行:
@Bean
public FormattingConversionService mvcConversionService() {
FormattingConversionService conversionService = new DefaultFormattingConversionService();
addFormatters(conversionService);
return conversionService;
}
老實說,當按照Spring文檔中的描述實現接口時,我不知道到底是什么失敗。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.