如何单元测试传入的Jersey MultiPart请求的处理

Pet*_*ete 8 java testing rest multipart jersey

我们有一个REST服务,它接受包含该hold 的MultiPart POST请求.在REST服务内部,可以根据提供的数据创建文件.BodyPartsInputStream

任务

我们希望根据其MultiPart输入对执行文件操作的类进行单元测试.注意:Wo不想使用Jersey-Test!Grizzly没有加载我们需要将DAO和fileHandler服务注入REST服务类的spring应用程序上下文.我们明确要测试我们的fileHandler服务如何处理multiPart数据.

然而问题是,MultiPartREST客户端发出的内容与REST服务器收到的内容不同,因为泽西可能会对数据进行流式传输或其他任何操作.尝试测试(见下文)以下设置将导致

IllegalArgumentException [B cannot be cast to com.sun.jersey.multipart.BodyPartEntity
Run Code Online (Sandbox Code Playgroud)

REST客户端 - 发送MultiPart

(只是片段,我省略了明显的东西):

    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);
Run Code Online (Sandbox Code Playgroud)

服务器端 - 接收MultiPart

休息:

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@Transactional
public Response create(MultiPart multiPart) {

    try {
            multiPartReader.saveFile(multiPart);
Run Code Online (Sandbox Code Playgroud)

服务器端MultiPartReader从多部分保存文件

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();
    }
Run Code Online (Sandbox Code Playgroud)

测试 - 隔离处理传入的MultiPart

现在我想测试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();
}
Run Code Online (Sandbox Code Playgroud)

但是,就像我说我得到了一个

IllegalArgumentException [B cannot be cast to com.sun.jersey.multipart.BodyPartEntity
Run Code Online (Sandbox Code Playgroud)

    BodyPartEntity bpe = (BodyPartEntity) multiPart.getBodyParts().get(0).getEntity();
Run Code Online (Sandbox Code Playgroud)

那么我该怎样做才能模拟由泽西处理的发送/接收,以便我的测试将获得与我的REST服务部署在服务器上并由REST客户端请求相同的数据?

编辑

运用

BodyPartEntity bpe = multiPart.getBodyParts().get(0).getEntityAs(BodyPartEntity.class);
Run Code Online (Sandbox Code Playgroud)

会抛出一个

IllegalStateException: Entity instance does not contain the unconverted content
Run Code Online (Sandbox Code Playgroud)

我认为,在调用我的MultiPartReader之前,还需要以某种方式转换测试生成的MultiPart.

在jersey中必须有一些方法,我可以调用它来执行此转换它的方式,当它在已部署的系统上发出MultiPart请求时,或者可能是接收端在接收HTTP请求时进行一些解析..?

Wil*_*ill 0

查看jersey-multipart文档,我看到:

“目前不可能提前知道应用程序更愿意为每个单独的正文部分使用哪个 Java 类,因此无法选择合适的 Provider。目前,返回的是每个正文部分的未解析内容(作为字节数组) ) 在返回的 BodyPart} 实例的实体属性中,应用程序可以根据该正文部分中包含的标头来决定需要采取哪些进一步的步骤。最简单的技术是检查接收到的 BodyPart,然后调用 getEntityAs() 方法一旦您知道您更喜欢哪个实现类。”

看来您需要遵循该建议。检查服务器端 MultiPartReader 代码中返回的字节数组:

multiPart.getBodyParts().get(0).getEntity();
Run Code Online (Sandbox Code Playgroud)

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