由于 ResourceConfig 不需要参数构造函数,Dropwizard 文件上传测试失败

Dropwizard file upload test failing due to ResourceConfig expecting no argument constructor

我有一个在 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) 需要无参数构造函数。如何在此处传递有关单参数构造函数的信息?

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

非常感谢。

当您将资源注册为 class

new ResourceConfig(FileUploadResource.class)

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

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

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