java如何单元测试传入Jersey多部分请求的处理
我们有一个REST服务,它接受MultiPart
POST请求,该请求包含BodyParts
个包含InputStream
个字符。在REST服务中,可以根据提供的数据创建一个文件
任务
我们希望对基于MultiPart
输入执行文件操作的类进行单元测试注意:我们不想使用球衣测试!Grizzly不加载spring应用程序上下文,我们需要将DAO和fileHandler服务注入REST服务类。我们明确希望测试fileHandler服务如何处理多部分数据
然而,问题是从REST客户机发出的MultiPart
与REST服务器收到的MultiPart
不同,因为jersey可能对数据做了一些处理以流式传输数据或其他任何操作。尝试测试(见下文)以下设置将导致
IllegalArgumentException [B cannot be cast to com.sun.jersey.multipart.BodyPartEntity
REST客户端-发送多部分
(只是片段,我省略了明显的东西):
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);
服务器端-接收多部分
其余:
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@Transactional
public Response create(MultiPart multiPart) {
try {
multiPartReader.saveFile(multiPart);
用于从多部分保存文件的服务器端多部分读取器
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, formatName, file);
}
bpe.close();
}
测试-隔离处理传入的多部分
现在我想测试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_OCTET_STREAM_TYPE)).
bodyPart(new BodyPart(fileName, MediaType.APPLICATION_XML_TYPE)).
bodyPart(new BodyPart(senderId, MediaType.APPLICATION_XML_TYPE));
multiPartReader.saveFile(multiPart);
file = new File(fileName);
Assert.assertNotNull(file);
Assert.assertTrue(file.getTotalSpace() > 0);
file.delete();
}
但是,就像我说的,我有一个
IllegalArgumentException [B cannot be cast to com.sun.jersey.multipart.BodyPartEntity
在
BodyPartEntity bpe = (BodyPartEntity) multiPart.getBodyParts().get(0).getEntity();
那么,我可以做些什么来模拟jersey处理的发送/接收,以便我的测试将获得与部署在服务器上并由REST客户端请求的REST服务相同的数据呢强>
编辑
使用
BodyPartEntity bpe = multiPart.getBodyParts().get(0).getEntityAs(BodyPartEntity.class);
将抛出一个
IllegalStateException: Entity instance does not contain the unconverted content
我认为,在调用我的MultiPartReader之前,必须以某种方式转换测试生成的MultiPart
jersey中必须有某种方法,我可以调用它,当它在已部署的系统上发送一个多部分请求时,或者接收端在接收HTTP请求时进行一些解析时,它会以这种方式进行转换
# 1 楼答案
看看我看到的jersey-multipart文档:
“目前无法提前知道应用程序希望为每个身体部位使用哪个Java类,因此无法选择合适的提供者。目前,每个身体部位的未分析内容都会返回(作为字节数组)在返回的BodyPart}实例的entity属性中,应用程序可以根据该body part中包含的头来决定需要执行哪些进一步的步骤。最简单的方法是检查接收到的BodyPart,然后在知道希望使用哪个实现类后调用getEntityAs()方法。"
看起来你需要遵循这个建议。检查服务器端多部件读取器代码中返回的字节数组:
。。。并在BodyPart上调用getEntityAs()