2013-09-02 3 views
2

У меня веб-приложение работает хорошо. Теперь я пытаюсь написать для него единичный тест. Мой веб-приложение имеет следующие conversionServiceConversionService, не работающий в модульном тесте (весна 3.2)

<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 просто не используется, а весной просто скажите мне

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")); 
} 

Что Im недостающее? Спасибо

+0

Включили ли вы конверсию в «applicationContext.xml» или «jpm-servlet.xml»? Есть ли какие-либо подсказки в журнале? Возможность, о которой я мог подумать, заключается в том, что весна не нашла ваш конверсионный сервис и не использовала значение по умолчанию, так как насчет изменения «conversionService» как «conversionService1»? – Hippoom

+0

conversionService находится в файле jpm-servlet.xml, но да, для некоторого неявного reaseon, тестовый контекст использует по умолчанию conversionService вместо моего :(выглядит как его игнорирование . I переименовали его, но не помогли – jpaoletti

+0

Не могли бы вы проверить свой журнал (заданный уровень для отладки), должно быть что-то вроде «define beans [conversionService1, mvcContentNegotiationManager», вы найдете другое создание конверсии? – Hippoom

ответ

0

У меня была такая же проблема. Если вы пытаетесь протестировать один контроллер, вы можете попробовать следующее:

@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")); 
} 

Надеюсь, что это поможет!

+0

Я посмотрю. Благодаря! – jpaoletti

0

Я понимаю, что это старая нить, но, как и я, будут другие, которые собираются споткнуться об этом в будущем, потратив несколько часов на устранение неполадок, почему их пользовательский конвертер не вызван.

Решение, предложенное @Mariano D'Ascanio, не является адекватным в тех случаях, когда нет контроллеров, по крайней мере, не тех, которые вы написали, например, когда вы используете Spring JPA. MockMvcBuilders.standaloneSetup требует, чтобы по меньшей мере один контроллер передавался конструктору, поэтому вы не можете использовать его для таких случаев. Способ обойти это путем введения org.springframework.core.convert.converter.ConverterRegistry или еще лучше, это подкласс org.springframework.core.convert.converter.FormatterRegistry, а затем в методе @PostContruct, зарегистрировать свой собственный конвертер/форматировщик, как показано ниже:

@PostConstruct 
void init() { 
    formatterRegistry.removeConvertible(String.class, OffsetDateTime.class); 

    formatterRegistry.addFormatter(customOffsetDateTimeFormatter); 
    formatterRegistry.addConverter(customOffsetDateTimeConverter); 
} 

Хитрость заключается в том, чтобы впрыснуть ConverterRegistry с помощью имя, а не тип, потому что для веб-тестов есть два регистратора конвертеров, по умолчанию и mvc. Тесты Spring используют конвертер по умолчанию, так что это тот, который вам нужен.

// GOTCHA ALERT: There's also a mvcConversionService; tests DO NOT use that 
@Resource(name = "defaultConversionService") 
private FormatterRegistry formatterRegistry; 

Надеюсь, что это поможет.

2

Mock конвертер Подобно этому,

GenericConversionService conversionService = new GenericConversionService(); 
    conversionService.addConverter(new StringToClass1Converter()); 



Deencapsulation.setField(FIXTURE, conversionService);