【发布时间】: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