【问题标题】:Dropwizard file upload test failing due to ResourceConfig expecting no argument constructor由于 ResourceConfig 没有参数构造函数,Dropwizard 文件上传测试失败
【发布时间】:2016-04-07 22:43:04
【问题描述】:

我在 Dropwizard 中实现了一个文件上传 REST 端点。我是新手,只是想学习。

@Path("/files")
@Produces(MediaType.APPLICATION_JSON)
public class FileUploadResource {

    private final MyAppWebConfiguration configuration;
    private static final Logger logger = LoggerFactory.getLogger(FileUploadResource.class);

    public FileUploadResource(MyAppWebConfiguration configuration) {
        this.configuration = configuration;
    }

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadFile(
            @FormDataParam("file") InputStream uploadedInputStream,
            @FormDataParam("file") FormDataContentDisposition fileDetail) throws IOException {

        logger.info("Request to upload the file ", fileDetail.getFileName());
        final String uploadedFileLocation = configuration.getCsvUploadPath();
        final String fileName = fileDetail.getFileName();
        writeToFile(uploadedInputStream, uploadedFileLocation, fileName);
        return Response.ok("File " + fileName + " is uploaded to the location " + uploadedFileLocation).build();
    }

    // save uploaded file to new location
    protected void writeToFile(InputStream uploadedInputStream, String uploadedFileLocation, String fileName) throws IOException {
        logger.info("Writing {} to {}", fileName, uploadedFileLocation);
        final java.nio.file.Path outputPath = FileSystems.getDefault().getPath(uploadedFileLocation, fileName);
        Files.copy(uploadedInputStream, outputPath, StandardCopyOption.REPLACE_EXISTING);
        logger.info("Uploaded {} to the location {}", fileName, uploadedFileLocation);
    }

代码运行良好,可以上传文件。 我正在尝试使用基于https://gist.github.com/psamsotha/218c6bbeb6164bac7cbc 的以下代码对其进行测试:

public class FileUploadResourceTest extends JerseyTest {

    private final static MyAppWebConfiguration mockConfiguration = mock(MyAppWebConfiguration.class);

    @Override
    public ResourceConfig configure() {
        return new ResourceConfig(FileUploadResource.class)
                .register(MultiPartFeature.class)
                .register(new LoggingFilter(Logger.getAnonymousLogger(), true));
    }

    @Override
    public void configureClient(ClientConfig config) {
        config.register(MultiPartFeature.class);
    }

    @Test
    public void test() {
        FileDataBodyPart filePart = new FileDataBodyPart("file", new File("/Users/rocky/Downloads/test.csv"));
        filePart.setContentDisposition(FormDataContentDisposition.name("file").fileName("/Users/rocky/Downloads/test.csv").build());

        MultiPart multiPart = new FormDataMultiPart()
                .bodyPart(filePart);
        Response response = target("/files").request()
                .post(Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE));
        assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
        response.close();
    }

此测试失败并出现以下错误:

WARNING: The following warnings have been detected: WARNING: HK2 service reification failed for [com.my.app.resources.FileUploadResource] with an exception:
MultiException stack 1 of 2
java.lang.NoSuchMethodException: Could not find a suitable constructor in com.my.app.resources.FileUploadResource class.
    at org.glassfish.jersey.internal.inject.JerseyClassAnalyzer.getConstructor(JerseyClassAnalyzer.java:192)
    at org.jvnet.hk2.internal.Utilities.getConstructor(Utilities.java:178)
    at org.jvnet.hk2.internal.ClazzCreator.initialize(ClazzCreator.java:128)
    at org.jvnet.hk2.internal.ClazzCreator.initialize(ClazzCreator.java:179)

FileUploadResource 中没有无参数构造函数,但 new ResourceConfig(FileUploadResource.class) 需要无参数构造函数。如何在此处传递有关单参数构造函数的信息?

这里的任何帮助将不胜感激。此外,请随时提出有关代码和测试的任何其他最佳实践,以便我改进它们。

非常感谢。

【问题讨论】:

  • 尝试了@peeskillet 的建议。现在有这个:FileDataBodyPart filePart = new FileDataBodyPart("file", new File("/Users/rocky/Downloads/test.csv")); filePart.setContentDisposition(FormDataContentDisposition.name("file").fileName("/Users/rocky/Downloads/test.csv").build()); MultiPart multiPart = new FormDataMultiPart() .bodyPart(filePart);。但是得到ERROR [2016-04-08 10:41:29,089] io.dropwizard.jersey.errors.LoggingExceptionMapper: Error handling a request: bdb68f36df42328e ! java.nio.file.NoSuchFileException: null/abc/Users/rocky/Downloads/test.csv
  • 将 test.csv 移动到相同的目录并更改了路径。现在,得到org.glassfish.jersey.test.inmemory.InMemoryConnector:Error while writing entity to the output stream. ! java.io.FileNotFoundException: test.csv (No such file or directory) ..javax.ws.rs.ProcessingException: Error while writing entity to the output stream. at FileUploadResourceTest.test(FileUploadResourceTest.java:51) Caused by: java.io.FileNotFoundException:test.csv (No such file or directory) at FileUploadResourceTest.test(FileUploadResourceTest.java:51)。第 51 行是.post(Entity.entity(multiPart, multiPart.getMediaType()));

标签: unit-testing mockito jersey-2.0 dropwizard jersey-test-framework


【解决方案1】:

当您将资源注册为类时

new ResourceConfig(FileUploadResource.class)

您是在告诉 Jersey 创建它。但它不知道如何创建它,因为只有一个接受配置对象的构造函数,Jersey 对此一无所知。相反,您应该只注册为一个对象。就像您在 Dropwizard (env.jersey().register(...)) 注册一样。

new ResourceConfig().regster(new FileUploadResource(mockConfiguration))
    ...

顺便说一句,使用 Dropwizard,我们不需要显式使用 JerseyTest。 Dropwizard 带有一个 JUnit 规则,它显式运行它自己的 JerseyTest,我们可以使用该规则对其进行配置。请参阅this issue,我在其中发布了一个完整的示例。

【讨论】:

    猜你喜欢
    • 2019-04-24
    • 1970-01-01
    • 2015-06-16
    • 1970-01-01
    • 2015-06-12
    • 2020-01-16
    • 1970-01-01
    • 2020-05-23
    • 2021-01-11
    相关资源
    最近更新 更多