After working most of the day I feel like I am fairly close to a solution on how to test a controller method which accepts file uploads from JUnit. My juint test code is as follows:
Map<String, String> postData = makePostMap(uploadForm);
File file = new File("test/resources/shared/uploads/blank.csv");
TemporaryFile temporaryFile = new TemporaryFile(file);
MultipartFormData.FilePart filePath = new MultipartFormData.FilePart(
"file",
"file.csv",
new scala.Some<>("text/csv"),
temporaryFile);
List<MultipartFormData.FilePart> fileParts = Lists.newArrayList(filePath);
scala.collection.immutable.Seq files = JavaConversions.asScalaBuffer(fileParts).toList();
Map<String, scala.collection.immutable.Seq<String>> postData2 = new HashMap<>();
for (String s : postData.keySet()) {
postData2.put(s, JavaConversions.asScalaBuffer(Lists.newArrayList(postData.get(s))).toList());
}
scala.collection.immutable.Map<String, scala.collection.immutable.Seq<String>> scalaMap =
JavaConversions.mapAsScalaMap(postData2).toMap(Predef.<Tuple2<String, scala.collection.immutable.Seq<String>>>conforms());
MultipartFormData formData = new MultipartFormData(scalaMap, files, null, null);
AnyContentAsMultipartFormData body = new AnyContentAsMultipartFormData(formData);
// run
login(employee);
String url = routes.ManageContacts.uploadCsv().url();
FakeRequest fakeRequest = new FakeRequest(POST, url).withBody(body);
fakeRequest = getAuthenticatedRequest(fakeRequest, employee);
result = route(fakeRequest);
assertThat(status(result)).isEqualTo(OK)
However, I get an exception (below) when the FakeRequest is routed to.
[error] Test controllers.ManageContactsTest.testUploadCsv failed: scala.MatchError: AnyContentAsMultipartFormData(MultipartFormData(Map(clearExisting -> List(false), survey -> List(11), bosMode -> List(false)),List(FilePart(file,file.csv,Some(text/csv),TemporaryFile(test/resources/shared/uploads/blank.csv))),null,null)) (of class play.api.mvc.AnyContentAsMultipartFormData), took 0.255 sec
[error] at play.api.test.RouteInvokers$class.jRoute(Helpers.scala:255)
[error] at play.api.test.Helpers$.jRoute(Helpers.scala:403)
[error] at play.api.test.Helpers.jRoute(Helpers.scala)
[error] at play.test.Helpers.route(Helpers.java:445)
[error] at play.test.Helpers.route(Helpers.java:437)
[error] at play.test.Helpers.route(Helpers.java:433)
[error] at controllers.ManageContactsTest.testUploadCsv(ManageContactsTest.java:121)
[error] ...
Diving down into the stack trace, I find the following scala match statement in the file:
/Users/jcreason/bin/playframework-2.3.8/framework/src/play-test/src/main/scala/play/api/test/Helpers.scala:253
def jRoute[T](app: Application, r: FakeRequest[T]): Option[Future[Result]] = {
(r.body: @unchecked) match {
case body: AnyContentAsFormUrlEncoded => route(app, r, body)
case body: AnyContentAsJson => route(app, r, body)
case body: AnyContentAsXml => route(app, r, body)
case body: AnyContentAsText => route(app, r, body)
case body: AnyContentAsRaw => route(app, r, body)
case body: AnyContentAsEmpty.type => route(app, r, body)
//case _ => MatchError is thrown
}
}
Since I'm passing through AnyContentAsMultipartFormData
, it throws this exception as it's not handled by the match. Does anyone know how to get around this? Or could point me in the direction of a different solution to this (aside from obvious answers just as selenium)?
For reference, I pulled some of this code from:
http://www.erol.si/2014/02/how-to-test-file-uploads-in-play-framework-java/