5

I'm using spring-mvc version 4.1.6-RELEASE with Junit 4.12 and java 1.7, I have a controller for file uploading who works when I've tested it on server with Browser. But when I try to test it with junit the mockfilemultipart is always empty and I'm sure isn't so in the test class.

This is my servlet-context.xml

<beans:beans xmlns="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.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />

<!--  beans:import resource="../controller-context.xml"/-->

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />

<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
</beans:bean>

<beans:bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

<context:component-scan base-package="it.isfol.iweb" />

This is the controller

package it.isfol.iweb.controller.pianoattivita;

import it.isfol.iweb.bean.wrappers.PianoAttivitaWrapper;
import it.isfol.iweb.controller.common.IsfolController;
import it.isfol.iweb.exceptions.IWebFatalException;
import it.isfol.iweb.service.pianoattivita.FilePianoAttivitaService;
import it.isfol.iweb.util.SessionConstant;

import java.util.Arrays;
import java.util.Collection;

import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class UploadPianoAttivitaController extends IsfolController {

    /**
     * 
     */
    private static final long        serialVersionUID = 5455170192118107020L;
    private static final String      UPLOAD_PAGE      = "upload/upload";
    private final Logger             logger           = LoggerFactory.getLogger(UploadPianoAttivitaController.class);
    @Autowired
    private FilePianoAttivitaService filePianoAttivitaService;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String uploadHomePage(HttpSession session) {
        logger.info("I'm home");
        return goToUploadPage(session);
    }

    @RequestMapping(value = "/uploadInit", method = RequestMethod.GET)
    public String uploadPageRedirect(HttpSession session) {
        logger.info("redirect into upload");
        return goToUploadPage(session);
    }

    @RequestMapping(value = "/uploadPiano", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE)
    @ResponseBody
    public String upload(@RequestParam("files[]") MultipartFile[] files, HttpSession session) throws IWebFatalException {
        logger.debug("Writing file to disk...");
        try {
            Collection<PianoAttivitaWrapper> piani = filePianoAttivitaService.getPianoAttivitaWrapperFromFiles(Arrays.asList(files), session.getId());
            session.setAttribute(SessionConstant.PIANO_ATTIVITA_LIST_WRAPPER, piani);
        } catch (IWebFatalException e) {
            throw e;
        } catch (Throwable t) {
            logger.error(t.getLocalizedMessage(), t);
            throw new IWebFatalException(t);
        }
        return "pianoAttivita";
    }

    private String goToUploadPage(HttpSession session) {
        logger.debug("redirect on upload page");
        sessionHelper.clearSessionPianoReference(session);
        return UPLOAD_PAGE;
    }

    public void setFilePianoAttivitaService(FilePianoAttivitaService filePianoAttivitaService) {
        this.filePianoAttivitaService = filePianoAttivitaService;
    }
}

Then my abstract class for testing

package it.isfol.iweb;

import java.io.IOException;
import java.util.Properties;

import org.junit.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@WebAppConfiguration(value = "src/main/webapp")
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml", "file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml" })
public abstract class IsfolIwebTester extends AbstractJUnit4SpringContextTests {

    private final Logger          logger         = LoggerFactory.getLogger(IsfolIwebTester.class);
    private Properties            testProperties = new Properties();
    @Autowired
    private WebApplicationContext webapp;
    protected MockMvc             mockMvc;

    @Before
    public void setup() {
        logger.debug("reading properties");
        try {
            testProperties.load(this.getClass().getResourceAsStream("/test-conf.properties"));
            this.mockMvc = MockMvcBuilders.webAppContextSetup(webapp).build();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        } catch (Throwable e) {
            logger.error(e.getLocalizedMessage(), e);
        }
    }

    public String getProperty(String key) {
        return testProperties.getProperty(key);
    }
}

and finally the test class who extends the class above

package it.isfol.iweb.pianoattivita;

import it.isfol.iweb.IsfolIwebTester;

import org.apache.commons.io.FilenameUtils;
import org.apache.tika.io.IOUtils;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

public class FilePianoAttivitaTester extends IsfolIwebTester {

    private final Logger logger = LoggerFactory.getLogger(FilePianoAttivitaTester.class);

    @Test
    public void testRunning() {
        logger.debug("Test started");
        try {
            String originalFile = getProperty("test.file.pianoattivita.path");
            String originalName = FilenameUtils.getName(originalFile);
            byte[] content = IOUtils.toByteArray(getClass().getResourceAsStream(originalFile));
            MockMultipartFile file = new MockMultipartFile("testJunit", originalName, null, content);
            this.mockMvc.perform(MockMvcRequestBuilders.fileUpload("/uploadPiano").file(file)).andExpect(MockMvcResultMatchers.status().isOk()).andReturn().equals("pianoAttivita");
            this.mockMvc.perform(MockMvcRequestBuilders.get("/pianoAttivita")).andExpect(MockMvcResultMatchers.view().name("upload/upload"));
        } catch(Throwable t) {
            logger.error(t.getLocalizedMessage(), t);
            Assert.fail();
        }
    }
}

In the method upload of UploadPianoAttivitaController when I run Junit the param files[] contain 1 empty MultiPartFile, while when I run it on server and I upload a file from page everything is ok.

theMan80
  • 83
  • 1
  • 7
  • are you sure that the path of the file is the same in the server's classpath , as it is in your project's classpath? – AntJavaDev Jun 17 '15 at 14:46
  • sorry maybe I haven't been clear, the junit test not work, the web application work, it's normal my test file is in another place, but my test class is able to read it, it is my controller who receve it from the MockMvcRequestBuilders an empty MultipartFile array. – theMan80 Jun 18 '15 at 15:18
  • you dont see any exception at controller's side or at junit ? only the empty parameter? are you sure that you are performing post request? – AntJavaDev Jun 18 '15 at 17:38

2 Answers2

2

The name of your RequestParam for files must match with the MockMultipartFile name.

In your case is "files []" and in the mock is "testJunit", you can watch your HttpServletRequest params in your controller.

J. Chomel
  • 8,193
  • 15
  • 41
  • 69
0

Try this way:

MockMultipartFile mockMultipartFile = new MockMultipartFile("file",
            "OriginalName.txt",
            "text/plain",
            rateExceptionsFile);

    mockMvc.perform(multipart(BASE_PATH + "/uploadFile")
            .file(mockMultipartFile)
            .contentType(MediaType.MULTIPART_FORM_DATA))
            .andExpect(status().isOk());
ivan2yk
  • 3
  • 1
  • 3