You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Steve Higham <st...@sjlt.co.uk> on 2012/04/25 12:07:50 UTC

StrutsTestCase, jUnit and file upload

I'm currently using StrutsTestCase and jUnit to component test my Actions
within the Struts context using a Mockito mock as my Model.

 

This is working fine. I can call request.setParamater ("paramName",
"paramValue") from the test class and, when executed, Struts will call the
corresponding setParamName ("paramValue") on my Action.

 

However I now wish to test "file upload" Actions. In normal use the
FileUploadInterceptor will call setUploadedFile (java.io.File file) on the
action. However I can't see any methods on the StrutsTestCase request object
which will prepare the request with an uploaded file. Has anyone got this to
work?

 

Steve Higham

 


Re: StrutsTestCase, jUnit and file upload

Posted by Chris Pratt <th...@gmail.com>.
First of all, I assume you're trying to test your own code, not the
framework. With that in mind, by the time the file gets to your action,
it's just a series of parameters (which could be slightly different
depending on which underlying Multipart support you are using).  So, my
suggestion would be to just mock in values for the parameters your action
is expecting.
  (*Chris*)

On Wed, Apr 25, 2012 at 6:36 AM, Gabriel Belingueres
<be...@gmail.com>wrote:

> Coincidentally, yesterday I was struggling with testing a file upload.
> I was not using S2 as web framework but I was using Commons
> Fileupload, which IIRC is the default S2 upload component.
>
> I must say that my first strategy was trying to use Spring's
> MockMultipartHttpServletRequest and MockMultipartFile to simulate the
> request, without any luck, so I ended up just writing the plain
> request by hand:
>
>    request = new MockHttpServletRequest();
>    request.setMethod("POST");
>    request.setContentType("multipart/form-data; boundary=AaB03x");
>
>    request.setContent(("--AaB03x\r\n" +
>        "Content-Disposition: form-data; name=\"archivo\";
> filename=\"texto.txt\"\r\n" +
>        "Content-Type: text/plain\r\n" +
>        "\r\n" +
>        "This is the content of the file\n" +
>        "\r\n" +
>        "--AaB03x\r\n" +
>        "Content-Disposition: form-data; name=\"id\"\r\n" +
>        "\r\n" +
>        "1\r\n" +
>        "--AaB03x--\r\n").getBytes("US-ASCII"));
>
> simulating the following form:
>
> <form method="post" action="controller?event=cargarMaterial"
> enctype="multipart/form-data">
>  <input type="hidden" name="id" value="${reunion.idreunion}"/>
>  <input type="file" name="archivo" size="50" />
>  <input type="submit" name="btnSubmit" value="Guardar" />
> </form>
>
> Important: respect the \r\n's and the final boundary with the extra
> "--" at the end of the form.
>
> commons upload version: 1.2.2.
>
> HTH,
> Gabriel
>
> 2012/4/25 Steve Higham <st...@sjlt.co.uk>:
> > I'm currently using StrutsTestCase and jUnit to component test my Actions
> > within the Struts context using a Mockito mock as my Model.
> >
> >
> >
> > This is working fine. I can call request.setParamater ("paramName",
> > "paramValue") from the test class and, when executed, Struts will call
> the
> > corresponding setParamName ("paramValue") on my Action.
> >
> >
> >
> > However I now wish to test "file upload" Actions. In normal use the
> > FileUploadInterceptor will call setUploadedFile (java.io.File file) on
> the
> > action. However I can't see any methods on the StrutsTestCase request
> object
> > which will prepare the request with an uploaded file. Has anyone got
> this to
> > work?
> >
> >
> >
> > Steve Higham
> >
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>

Re: StrutsTestCase, jUnit and file upload

Posted by Gabriel Belingueres <be...@gmail.com>.
Coincidentally, yesterday I was struggling with testing a file upload.
I was not using S2 as web framework but I was using Commons
Fileupload, which IIRC is the default S2 upload component.

I must say that my first strategy was trying to use Spring's
MockMultipartHttpServletRequest and MockMultipartFile to simulate the
request, without any luck, so I ended up just writing the plain
request by hand:

    request = new MockHttpServletRequest();
    request.setMethod("POST");
    request.setContentType("multipart/form-data; boundary=AaB03x");

    request.setContent(("--AaB03x\r\n" +
        "Content-Disposition: form-data; name=\"archivo\";
filename=\"texto.txt\"\r\n" +
        "Content-Type: text/plain\r\n" +
        "\r\n" +
        "This is the content of the file\n" +
        "\r\n" +
        "--AaB03x\r\n" +
        "Content-Disposition: form-data; name=\"id\"\r\n" +
        "\r\n" +
        "1\r\n" +
        "--AaB03x--\r\n").getBytes("US-ASCII"));

simulating the following form:

<form method="post" action="controller?event=cargarMaterial"
enctype="multipart/form-data">
  <input type="hidden" name="id" value="${reunion.idreunion}"/>
  <input type="file" name="archivo" size="50" />
  <input type="submit" name="btnSubmit" value="Guardar" />
</form>

Important: respect the \r\n's and the final boundary with the extra
"--" at the end of the form.

commons upload version: 1.2.2.

HTH,
Gabriel

2012/4/25 Steve Higham <st...@sjlt.co.uk>:
> I'm currently using StrutsTestCase and jUnit to component test my Actions
> within the Struts context using a Mockito mock as my Model.
>
>
>
> This is working fine. I can call request.setParamater ("paramName",
> "paramValue") from the test class and, when executed, Struts will call the
> corresponding setParamName ("paramValue") on my Action.
>
>
>
> However I now wish to test "file upload" Actions. In normal use the
> FileUploadInterceptor will call setUploadedFile (java.io.File file) on the
> action. However I can't see any methods on the StrutsTestCase request object
> which will prepare the request with an uploaded file. Has anyone got this to
> work?
>
>
>
> Steve Higham
>
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


RE: StrutsTestCase, jUnit and file upload

Posted by Steve Higham <st...@sjlt.co.uk>.
Thanks to Chris, Gabriel for your comments.

I finally got this to work yesterday. A neat solution probably requires
refactoring StrutsTestCase and deriving a new class
(StrutsMultipartTestCase) from it. In the meantime the following changes
will work subject to a couple of limitations: -

This only supports upload of a single file - although fairly simple to
extend for multiple files.
I've use Mockito for a couple of mocks
It's not very clean :-(

First you need spring-web-x.y.z.jar on your classpath. This comes with the
junit plugin.

Your test class needs the following override. This is a cut & paste job from
StrutsTestCase except for the request creation line.

/**
 * We need to override this method so we can use class 
 * MockMultipartHttpServletRequest for the request.
 */
@Override
protected void initServletMockObjects() 
{
  servletContext = new MockServletContext(resourceLoader);
  response = new MockHttpServletResponse();
  request = new MockMultipartHttpServletRequest();
  pageContext = new MockPageContext(servletContext, request, response);
}

We now need a new version of getActionProxy with additional parameters as
follows: -

/**
 * We need our own version to handle the file uploading
 * @param uri  struts action uri
 * @param contentType  mime content type
 * @param filename  name reported to action
 * @param file  uploaded file
 * @return  ActionProxy
 */
protected ActionProxy 
getActionProxy (String uri, String contentType, String filename, File file)
{
	// Create the proxy
	ActionProxy result = super.getActionProxy (uri);

	// Not part of upload but I think required for SessionAware
	ActionContext context = result.getInvocation ().getInvocationContext
();
	if (context.getSession () == null)
	{
		context.setSession (new HashMap<String, Object> ());
	}
	
	// Wrap the request in a MultiPartRequestWrapper
	MultiPartRequest mpr = 
			createMultiPartRequest (contentType, filename,
file);
	MultiPartRequestWrapper wrapper = 
			new MultiPartRequestWrapper (mpr, request, null);
	ServletActionContext.setRequest (wrapper);
	
	return result;
}

protected MultiPartRequest 
createMultiPartRequest (String contentType, String fileName, File file)
{
	MultiPartRequest result = Mockito.mock (MultiPartRequest.class);
	Vector<String> fileParameterNames = new Vector<String> ();
	fileParameterNames.add (PROP_NAME);
	Enumeration<String> enumFpn = fileParameterNames.elements ();
	Mockito.when (result.getFileParameterNames ()).thenReturn (enumFpn);
	String [] contentTypes = new String [1];
	contentTypes [0] = contentType;
	Mockito.when (result.getContentType (PROP_NAME)).thenReturn
(contentTypes);
	String [] fileNames = new String [1];
	fileNames [0] = fileName;
	Mockito.when (result.getFileNames (PROP_NAME)).thenReturn
(fileNames);
	File [] files = new File [1];
	files [0] = file;
	Mockito.when (result.getFile (PROP_NAME)).thenReturn (files);
	
	return result;
}

private static final String PROP_NAME = "propertyName";

This assumes that your upload action has methods setPropertyName (File),
setPropertyNameContentType (String), setPropertyNameFileName (String).

The @Test methods now include the following: -

File uploadedFile = new File ("path to test file");
ActionProxy proxy = getActionProxy ("uri", "content type e.g. text/csv",
file.getName (), file);
assertTrue (proxy.execute ().equals ("expected action result");

Note that the calls to the action are generated internally. You don't need
any request.setParameter (...) calls.

Cheers,

Steve

-----Original Message-----
From: Steve Higham [mailto:steve@sjlt.co.uk] 
Sent: 25 April 2012 11:08
To: 'Struts Users Mailing List'
Subject: StrutsTestCase, jUnit and file upload

I'm currently using StrutsTestCase and jUnit to component test my Actions
within the Struts context using a Mockito mock as my Model.

 

This is working fine. I can call request.setParamater ("paramName",
"paramValue") from the test class and, when executed, Struts will call the
corresponding setParamName ("paramValue") on my Action.

 

However I now wish to test "file upload" Actions. In normal use the
FileUploadInterceptor will call setUploadedFile (java.io.File file) on the
action. However I can't see any methods on the StrutsTestCase request object
which will prepare the request with an uploaded file. Has anyone got this to
work?

 

Steve Higham

 



---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org