客户端发布多部分表单数据

Client posting multipart form data

我正在尝试创建一个用于测试我的控制器的客户端

控制器

@Secured(SecurityRule.IS_AUTHENTICATED)
@Controller
class InjuryController(private val userService: UserService, private val injuryService: InjuryService) {
...
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Post("/injuries/{id}/images")
    fun postImage(id: Long, file: CompletedFileUpload, principal: Principal): HttpResponse<*>? {
        ...
        return HttpResponse.ok(imageReference)
    }
...
}

客户

@Client("/")
interface InjuryClient {
    @Post("/injuries/{id}/images", produces = [MULTIPART_FORM_DATA])
    fun postImage(id: Long, body: MultipartBody, @Header authorization: String): ImageReference
}

测试

@Test
fun `Post an image an injury`() {
    // Given
    val description = "description"
    val occurredAt = LocalDateTime.now()
    val id = createInjury(description, occurredAt).id

    val toWrite = "test file"
    val file = File.createTempFile("data", ".txt")
    FileWriter(file).apply {
        write(toWrite)
        close()
    }

    val requestBody = MultipartBody.builder()
            .addPart("data",
                    file.name,
                    MediaType.TEXT_PLAIN_TYPE,
                    file
            ).build()

    // When
    val response = injuryClient.postImage(id, requestBody, authorization)

    // Then
    assertEquals("$id:${file.name}", response.key)
}

错误

The type java.util.LinkedHashMap is not a supported type for a multipart request body
io.micronaut.http.multipart.MultipartException: The type java.util.LinkedHashMap is not a supported type for a multipart request body
    at io.micronaut.http.client.DefaultHttpClient.buildMultipartRequest(DefaultHttpClient.java:2063)
    at io.micronaut.http.client.DefaultHttpClient.buildNettyRequest(DefaultHttpClient.java:1480)
    at io.micronaut.http.client.DefaultHttpClient.sendRequestThroughChannel(DefaultHttpClient.java:1599)
    at io.micronaut.http.client.DefaultHttpClient.lambda$null(DefaultHttpClient.java:1035)
    at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:577)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:570)
    at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:549)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:490)
    at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:615)
    at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:604)
    at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:104)
    at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:84)
    at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.fulfillConnectPromise(AbstractNioChannel.java:300)
    at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:335)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:688)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514)
    at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:1044)
    at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:834)

关于如何消除该错误的任何线索?

客户端假定方法参数是主体的成员,而不是每个代表整个主体。您可以通过使用 @Body

注释客户端中的 body 参数来实现所需的行为