web-dev-qa-db-fra.com

Utilisation du test Spring MVC pour le test unitaire en plusieurs parties POST demande

J'ai le gestionnaire de requêtes suivant pour sauvegarder les autos. J'ai vérifié que cela fonctionne lorsque j'utilise par exemple boucle. Maintenant, je veux tester la méthode avec Spring MVC Test. J'ai essayé d'utiliser fileUploader, mais je ne parviens pas à le faire fonctionner. Je ne parviens pas non plus à ajouter la partie JSON. 

Comment pourrais-je tester cette méthode avec Spring MVC Test? Je ne suis pas en mesure de trouver des exemples à ce sujet.

@RequestMapping(value = "autos", method = RequestMethod.POST)
public ResponseEntity saveAuto(@RequestPart(value = "data") AutoResource,
                                   @RequestParam(value = "files[]", required = false) List<MultipartFile> files) {...}

Je souhaite utiliser une représentation JSON pour mon auto + un ou plusieurs fichiers.

Je vais ajouter 100 en prime à la bonne réponse!

80
LuckyLuke

Puisque MockMvcRequestBuilders#fileUpload est obsolète, vous voudrez utiliser MockMvcRequestBuilders#multipart(String, Object...) qui retourne un MockMultipartHttpServletRequestBuilder . Puis enchaînez un tas de file(MockMultipartFile) calls.

Voici un exemple de travail. Étant donné un @Controller

@Controller
public class NewController {

    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @ResponseBody
    public String saveAuto(
            @RequestPart(value = "json") JsonPojo pojo,
            @RequestParam(value = "some-random") String random,
            @RequestParam(value = "data", required = false) List<MultipartFile> files) {
        System.out.println(random);
        System.out.println(pojo.getJson());
        for (MultipartFile file : files) {
            System.out.println(file.getOriginalFilename());
        }
        return "success";
    }

    static class JsonPojo {
        private String json;

        public String getJson() {
            return json;
        }

        public void setJson(String json) {
            this.json = json;
        }

    }
}

et un test unitaire 

@WebAppConfiguration
@ContextConfiguration(classes = WebConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class Example {

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Test
    public void test() throws Exception {

        MockMultipartFile firstFile = new MockMultipartFile("data", "filename.txt", "text/plain", "some xml".getBytes());
        MockMultipartFile secondFile = new MockMultipartFile("data", "other-file-name.data", "text/plain", "some other type".getBytes());
        MockMultipartFile jsonFile = new MockMultipartFile("json", "", "application/json", "{\"json\": \"someValue\"}".getBytes());

        MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
        mockMvc.perform(MockMvcRequestBuilders.multipart("/upload")
                        .file(firstFile)
                        .file(secondFile)
                        .file(jsonFile)
                        .param("some-random", "4"))
                    .andExpect(status().is(200))
                    .andExpect(content().string("success"));
    }
}

Et la classe @Configuration

@Configuration
@ComponentScan({ "test.controllers" })
@EnableWebMvc
public class WebConfig extends WebMvcConfigurationSupport {
    @Bean
    public MultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        return multipartResolver;
    }
}

Le test devrait réussir et vous donner la sortie de

4 // from param
someValue // from json file
filename.txt // from first file
other-file-name.data // from second file

Le fait à noter est que vous envoyez le JSON comme tout autre fichier multipart, sauf avec un type de contenu différent.

200
Sotirios Delimanolis

Jetez un coup d’œil à cet exemple tiré de la vitrine printanière MVC, c’est le lien vers le code source :

@RunWith(SpringJUnit4ClassRunner.class)
public class FileUploadControllerTests extends AbstractContextControllerTests {

    @Test
    public void readString() throws Exception {

        MockMultipartFile file = new MockMultipartFile("file", "orig", null, "bar".getBytes());

        webAppContextSetup(this.wac).build()
            .perform(fileUpload("/fileupload").file(file))
            .andExpect(model().attribute("message", "File 'orig' uploaded successfully"));
    }

}
16
Angular University

La méthode MockMvcRequestBuilders.fileUpload est obsolète. Utilisez plutôt MockMvcRequestBuilders.multipart

Ceci est un exemple:

import static org.hamcrest.CoreMatchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.MultipartFile;


/**
 * Unit test New Controller.
 *
 */
@RunWith(SpringRunner.class)
@WebMvcTest(NewController.class)
public class NewControllerTest {

    private MockMvc mockMvc;

    @Autowired
    WebApplicationContext wContext;

    @MockBean
    private NewController newController;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(wContext)
                   .alwaysDo(MockMvcResultHandlers.print())
                   .build();
    }

   @Test
    public void test() throws Exception {
       // Mock Request
        MockMultipartFile jsonFile = new MockMultipartFile("test.json", "", "application/json", "{\"key1\": \"value1\"}".getBytes());

        // Mock Response
        NewControllerResponseDto response = new NewControllerDto();
        Mockito.when(newController.postV1(Mockito.any(Integer.class), Mockito.any(MultipartFile.class))).thenReturn(response);

        mockMvc.perform(MockMvcRequestBuilders.multipart("/fileUpload")
                .file("file", jsonFile.getBytes())
                .characterEncoding("UTF-8"))
        .andExpect(status().isOk());

    }

}
10
Romina Liuzzi

Si vous utilisez Spring4/SpringBoot 1.x, sachez que vous pouvez également ajouter des parties "text" (json). Cela peut se faire via MockMvcRequestBuilders.fileUpload (). File (fichier MockMultipartFile) (nécessaire car la méthode .multipart() n'est pas disponible dans cette version:

@Test
public void test() throws Exception {

   mockMvc.perform( 
       MockMvcRequestBuilders.fileUpload("/files")
         // file-part
         .file(makeMultipartFile( "file-part" "some/path/to/file.bin", "application/octet-stream"))
        // text part
         .file(makeMultipartTextPart("json-part", "{ \"foo\" : \"bar\" }", "application/json"))
       .andExpect(status().isOk())));

   }

   private MockMultipartFile(String requestPartName, String filename, 
       String contentType, String pathOnClassPath) {

       return new MockMultipartFile(requestPartName, filename, 
          contentType, readResourceFile(pathOnClasspath);
   }

  // make text-part using MockMultipartFile
  private MockMultipartFile makeMultipartTextPart(String requestPartName, 
      String value, String contentType) throws Exception {

      return new MockMultipartFile(requestPartName, "", contentType,
               value.getBytes(Charset.forName("UTF-8")));   
  }


 private byte[] readResoueceFile(String pathOnClassPath) throws Exception {
      return Files.readAllBytes(Paths.get(Thread.currentThread().getContextClassLoader()
         .getResource(pathOnClassPath).toUri()))l
   }

}
0
walkeros