簡體   English   中英

ConversionService在單元測試中不起作用(春季3.2)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM