英文:
Dropwizard DropwizardAppRule test multipart file upload
问题
我目前正在尝试通过调用一个以 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、类型为类 org.glassfish.jersey.media.multipart.FormDataMultiPart、泛型类型为类 org.glassfish.jersey.media.multipart.FormDataMultiPart 的 MessageBodyWriter。
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: 找不到适用于介质类型为 multipart/form-data、类型为类 org.glassfish.jersey.media.multipart.FormDataMultiPart、泛型类型为类 org.glassfish.jersey.media.multipart.FormDataMultiPart 的 MessageBodyWriter。
请注意,在应用程序引导中有必要注册 multipart:
private List<Resource> configureJersey(Configuration config, Environment environment) {
// 添加一些必需的功能
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);
}
就像你建议的那样。
英文:
I'm currently trying to write an IT test by calling a resource that takes MultiPartFormData as input.
It work when the application starts "normaly" but doesn't when started with DropwizardAppRule helper.
Here is my code :
@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 is intanciated like so :
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);
}
}
I get the following error :
> MessageBodyWriter not found for media type=multipart/form-data, type=class org.glassfish.jersey.media.multipart.FormDataMultiPart, genericType=class org.glassfish.jersey.media.multipart.FormDataMultiPart.
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=multipart/form-data, type=class org.glassfish.jersey.media.multipart.FormDataMultiPart, genericType=class org.glassfish.jersey.media.multipart.FormDataMultiPart.
Note that there is the required registering of multipart in Application bootstrap :
private List<Resource> configureJersey(Configuration config, Environment environment) {
// adds some required features
environment.jersey().register(MultiPartFeature.class);
UPDATE:
Thanks @paul-samsotha for taking time to answer.
I did the following:
@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);
}
Just like you suggest.
答案1
得分: 1
错误发生在客户端在发送请求之前。查看关于表单的文档,它会告诉你在客户端也需要注册 MultiPartFeature
。你可以通过 Client
或者 WebTarget
进行注册。Dropwizard 建议你在 WebTarget
中进行注册,就像示例中所示。
var response = QORUS_APP.client()
.target(...)
.register(MultiPartFeature.class)
...
英文:
The error is occurring on the client side before it sends out the request. See the docs on Forms, it will show you that you need to register the MultiPartFeature
on the client side also. You can register it either with the Client
or the WebTarget
. Dropwizard suggests you register it with the WebTarget
, as shown in the example.
var response = QORUS_APP.client()
.target(...)
.register(MultiPartFeature.class)
...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论