有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何单元测试传入Jersey多部分请求的处理

我们有一个REST服务,它接受MultiPartPOST请求,该请求包含BodyParts个包含InputStream个字符。在REST服务中,可以根据提供的数据创建一个文件

任务

我们希望对基于MultiPart输入执行文件操作的类进行单元测试注意:我们不想使用球衣测试!Grizzly不加载spring应用程序上下文,我们需要将DAO和fileHandler服务注入REST服务类。我们明确希望测试fileHandler服务如何处理多部分数据

然而,问题是从REST客户机发出的MultiPartREST服务器收到的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) 个答案

  1. # 1 楼答案

    看看我看到的jersey-multipart文档:

    “目前无法提前知道应用程序希望为每个身体部位使用哪个Java类,因此无法选择合适的提供者。目前,每个身体部位的未分析内容都会返回(作为字节数组)在返回的BodyPart}实例的entity属性中,应用程序可以根据该body part中包含的头来决定需要执行哪些进一步的步骤。最简单的方法是检查接收到的BodyPart,然后在知道希望使用哪个实现类后调用getEntityAs()方法。"

    看起来你需要遵循这个建议。检查服务器端多部件读取器代码中返回的字节数组:

    multiPart.getBodyParts().get(0).getEntity();
    

    。。。并在BodyPart上调用getEntityAs()