Java – how to unit test the processing of incoming Jersey multipart requests
We have a rest service that accepts multipart post requests containing bodyparts that save inputstreams Within the rest service, files can be created based on the data provided
task
We want to unit test classes that perform file operations based on their multipart input Note: Wo doesn't want to use Jersey test! Grizzly does not load the spring application context where we need to inject Dao and filehandler services into the rest service class We specifically want to test how our filehandler service handles multipart data
However, the problem is that the multipart sent from the rest client is different from the multipart received by the rest server, because Jersey may stream data or perform any other operations Attempting to test (see below) the following settings will cause
IllegalArgumentException [B cannot be cast to com.sun.jersey.multipart.BodyPartEntity
Rest client – send multipart
(just a fragment, I omitted the obvious):
byte[] bytes = FileManager.readImageFileToArray(completePath,fileType); MultiPart multiPart = new MultiPart(). bodyPart(new BodyPart(bytes,MediaType.APPLICATION_OCTET_STREAM_TYPE)). bodyPart(new BodyPart(fileName,MediaType.APPLICATION_XML_TYPE)). bodyPart(new BodyPart(senderId,MediaType.APPLICATION_XML_TYPE)); ClientConfig cc = new DefaultClientConfig(); cc.getClasses().add(MultiPartWriter.class); Client client = Client.create(cc); WebResource webResource = client.resource(requestUrl); Builder builder = webResource.type(MediaType.MULTIPART_FORM_DATA_TYPE); builder = addHeaderParams(builder,headerParams); ClientResponse response = builder.post(ClientResponse.class,multiPart);
Server side – receive multipart
Rest:
@POST @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) @Transactional public Response create(MultiPart multiPart) { try { multiPartReader.saveFile(multiPart);
The server-side multipartreader saves files from multiple parts
public class MultiPartReader { public void saveFile(MultiPart multiPart) throws IOException { BodyPartEntity bpe = (BodyPartEntity) multiPart.getBodyParts().get(0).getEntity(); InputStream inputStream = bpe.getInputStream(); // ... BufferedImage bi = ImageIO.read(inputStream); String fileName = getFileNameFromMultiPart(multiPart); File file = new File(filename); if (file.isDirectory()) { ImageIO.write(bi,formatName,file); } else { file.mkdirs(); ImageIO.write(bi,file); } bpe.close(); }
Test – isolate incoming multipart
Now I want to test the multipartreader:
@Test public void saveFile_should_Create_file() throws IOException { byte[] bytes = IoUtils.toByteArray(this.getClass().getResourceAsStream(fileResource)); MultiPart multiPart = new MultiPart(). bodyPart(new BodyPart(bytes,MediaType.APPLICATION_XML_TYPE)); multiPartReader.saveFile(multiPart); file = new File(fileName); Assert.assertNotNull(file); Assert.assertTrue(file.getTotalSpace() > 0); file.delete(); }
But, like I said, I got one
IllegalArgumentException [B cannot be cast to com.sun.jersey.multipart.BodyPartEntity
stay
BodyPartEntity bpe = (BodyPartEntity) multiPart.getBodyParts().get(0).getEntity();
So what can I do to simulate sending / receiving processed by Jersey so that my test will get the same data as my rest Service deployed on the server and requested by the rest client?
edit
application
BodyPartEntity bpe = multiPart.getBodyParts().get(0).getEntityAs(BodyPartEntity.class);
Will throw a
IllegalStateException: Entity instance does not contain the unconverted content
I think that before calling my multipart reader, I need to convert the multipart generated by the test in some way
There must be some methods in Jersey. I can call it to perform this transformation. When it sends a multipart request on the deployed system, or the receiving end may perform some parsing when receiving an HTTP request?
Solution
Looking at the Jersey Multipart Document, I see:
"At present, it is impossible to know in advance what Java classes the application wants to use for each individual body part, so the appropriate provider cannot be selected. At present, the unresolved content of each body part is returned (as a byte array) )In the entity properties of the returned bodypart} instance, the application can determine what further steps are required according to the header contained in the body part The easiest way is to check the received BodyPart and then call the getEntityAs () method once you know which implementation class you want. “
It seems that you need to follow this advice Check the byte array returned in the server side multipartreader Code:
multiPart.getBodyParts().get(0).getEntity();
... and call getentityas() on the bodypart