【问题标题】:Dropwizard DropwizardAppRule test multipart file uploadDropwizard DropwizardAppRule 测试分段文件上传
【发布时间】:2021-01-23 07:34:47
【问题描述】:

我目前正在尝试通过调用以 MultiPartFormData 作为输入的资源来编写 IT 测试。

它在应用程序“正常”启动时工作,但在使用 DropwizardAppRule 帮助器启动时不起作用。

这是我的代码:

@Test
public void importProductAndOfferCsvShopInput() {
    // Given
    var shopId = "id";
    var multipartHeaders = headers;
    multipartHeaders.putSingle("Content-Type", "multipart/form-data");

    var file = new File("src/test/resources/import/products&offers.csv");
    var fileDataBodyPart = new FileDataBodyPart("file", file, MediaType.APPLICATION_OCTET_STREAM_TYPE);
    MultiPart multiPart = new FormDataMultiPart().bodyPart(fileDataBodyPart, MediaType.MULTIPART_FORM_DATA_TYPE);

    // When
    var response = QORUS_APP.client().target(String.format("http://localhost:%d/ui/shop-inputs/csv/%s", 8082, shopId))
                            .queryParam("importContentType", "BOTH")
                            .request()
                            .headers(multipartHeaders)
                            .post(Entity.entity(multiPart, multiPart.getMediaType()));

    // Then
    assertThat(response.getStatusInfo()).isEqualTo(Response.Status.OK);
}

QORUS_APP 是这样被催眠的:

public abstract class AbstractRestResourceTest {

    @ClassRule
    public static final DropwizardAppRule<Configuration> QORUS_APP = ResourceSuite.QORUS_APP;
    private static final String USER_API_KEY = "authenticatedUserApiKey";

    protected static MultivaluedMap<String, Object> headers;

    public AbstractRestResourceTest() {
        headers = new MultivaluedHashMap<>();
        headers.putSingle("Content-Type", "application/json");
        headers.putSingle("Accept", "*/*");
        headers.putSingle(NgTokenAuthFilter.AUTHORIZATION_HEADER, "Bearer " + USER_API_KEY);
    }
}

我收到以下错误:

找不到媒体类型=multipart/form-data、类型=class org.glassfish.jersey.media.multipart.FormDataMultiPart、genericType=class org.glassfish.jersey.media.multipart.FormDataMultiPart 的MessageBodyWriter。 org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter 找不到媒体类型=multipart/form-data, type=class org.glassfish.jersey.media.multipart.FormDataMultiPart, genericType=class org.glassfish.jersey.media .multipart.FormDataMultiPart。

请注意,在应用程序引导中需要注册多部分:

    private List<Resource> configureJersey(Configuration config, Environment environment) {
    // adds some required features
    environment.jersey().register(MultiPartFeature.class);

更新:

感谢@paul-samsotha 花时间回答。

我做了以下事情:

@Test
public void importProductAndOfferCsvShopInput() {
    // Given
    var shopId = "5b03ebe9c9aa0423b4a73dce";
    var multipartHeaders = headers;
    multipartHeaders.putSingle("Content-Type", "multipart/form-data");

    var file = new File("src/test/resources/import/products&offers.csv");
    var fileDataBodyPart = new FileDataBodyPart("file", file);
    var multiPart = new FormDataMultiPart().bodyPart(fileDataBodyPart);

    // When
    var response = QORUS_APP.client()
                            .target(String.format("http://localhost:%d/ui/shop-inputs/csv/%s", 8082, shopId))
                            .register(MultiPartFeature.class)
                            .queryParam("importContentType", "BOTH")
                            .request()
                            .headers(multipartHeaders)
                            .post(Entity.entity(multiPart, multiPart.getMediaType()));

    // Then
    assertThat(response.getStatusInfo()).isEqualTo(Response.Status.OK);
}

就像你建议的那样。

【问题讨论】:

  • .bodyPart(fileDataBodyPart, MediaType.MULTIPART_FORM_DATA_TYPE)这部分的媒体类型不应该是multpart。您甚至不需要第二个参数,因为您在构造 FileDataBodyPart 时已经设置了媒体类型
  • 好的,我就是这么做的。删除了正文部分的 MediaType。你能向我解释为什么它不应该是多部分的,而是它是什么?非常感谢您的帮助。
  • multipart 是 entire 实体的媒体类型。之所以称为多部分,是因为有多个部分,每个部分都是自己的独立实体,具有自己独立的内容类型。在这种情况下,文件的内容类型为 application/octet-stream,正如您在构造 FileDataBodyPart 时声明的那样。
  • 抱歉,您在构建 FileDataBodyPart 时没有设置媒体类型。但是有三种不同的构造函数,一种允许你传递 MediaType。您正在使用的 javadoc 声明:“使用提供的名称和文件构造正文部分,它预测所提供文件的 MediaType。对于已知的媒体类型,客户端不需要显式设置媒体类型。 " 如您所见,这只是猜测。您可以按照您的尝试将其添加到bodyPart() 的调用中,但在这种情况下,您将使用类似 application/csv
  • 好的,我现在很清楚了。非常感谢您的解释。

标签: java jersey dropwizard


【解决方案1】:

错误发生在客户端发出请求之前。 See the docs on Forms,它会告诉你你需要在客户端注册MultiPartFeature。您可以使用ClientWebTarget 注册它。 Dropwizard 建议您使用WebTarget 注册它,如示例所示。

var response = QORUS_APP.client()
        .target(...)
        .register(MultiPartFeature.class)
        ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 1970-01-01
    • 2013-07-07
    • 1970-01-01
    • 2015-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多