Précédemment, nous avons vu comment ajouter le support du format CSV dans Spring MVC au moyen des MessageConverter. Il est maintenant temps d’automatiser les tests de ce composant. Pour cela, il faut utiliser Spring MVC Test framework.

Dans un premier temps, il faut déclarer un context Spring simplifié pour le test dans un fichier test-web-context.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:mvc="http://www.springframework.org/schema/mvc"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
  <context:component-scan base-package="com.mycompany.myproject.web.mvc.controler" />
</beans:beans>

Ensuite, il faut écrire un test unitaire qui va :

  • configurer le MessageConverter à tester
  • charger le contrôleur à tester
  • mocker les services du contrôleur
  • tester le comportement des requêtes proposées par le contrôleur

Voici le code du test unitaire utilisant Spring Test ainsi que Mockito :

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:test-web-context.xml" })
@WebAppConfiguration
public class StatsControllerTest {
  private static final String CSV_TEST_FILE = "src/test/resources/test.csv";

  @Autowired
  private StatsController statsController;

  @Autowired
  private CsvMessageConverter csvMessageConverter;

  @Autowired
  private StatsService statsService;

  private MockMvc mockMvc;

  private String csvContent;

  @Before
  public void setUp() {
    // charge le mock MVC et configure le CsvMessageConverter à tester
    mockMvc = MockMvcBuilders.standaloneSetup(statsController)
      .setMessageConverters(csvMessageConverter).build();

    // "mocke" le service utilisé par le StatsController à tester
    CsvReader reader = new CsvReader(new FileReader(CSV_TEST_FILE));
    List records = reader.readAllRecords();
    when(statsService.findAllStats(anyInt(), anyInt())).thenReturn(records);

    // charge le jeu de test
    csvContent = new String(Files.readAllBytes(Paths.get(CSV_TEST_FILE)));
  }

  @Test
  public void testGetAllStats() throws Exception {
    // exécute la requête HTTP GET, affiche des traces dans la console et vérifie le retour
    mockMvc.perform(get("/stats/2013/08.csv")).andDo(print())
      .andExpect(status().isOk())
      .andExpect(content().contentType("text/csv;charset=UTF-8"))
      .andExpect(content().string(csvContent));
    verify(statsService).findAllStats(2013, 8);
 }

  @Test
  public void testSaveAllStats() throws Exception {
    // exécute la requête HTTP POST, affiche des traces dans la console et vérifie le retour
    mockMvc.perform(
      post("/stats/2013/08").contentType(
        new MediaType("text", "csv", Charset.forName("utf-8")))
        .content(csvContent)).andDo(print())
      .andExpect(status().isOk())
      .andExpect(content().string(csvContent));
    verify(statsService).saveAllStats(2013, 8, Mockito.anyList());
    }

  @Configuration
  @EnableWebMvc
  public static class TestConfiguration {
    @Bean
    public StatsService statsService() {
      return Mockito.mock(StatsService.class);
    }
  }
}

Comme vous pouvez le constater, la mise en place du test est assez simple. Notez que des importations statiques ont été réalisées afin d’utiliser la fluent API :

import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

Même si le prétexte de l’article est de donner la méthode pour tester un MessageConverter, vous avez ici toutes les informations de base pour réaliser les tests unitaires de vos contrôleurs implémentés avec Spring MVC.

Vous n’aurez maintenant plus d’excuse pour ne pas avoir automatisé les tests unitaires de vos contrôleurs (de la couche MVC) ! 😛