I'm trying to create a client which I use to test my controller
The controller
@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)
}
...
}
The client
@Client("/")
interface InjuryClient {
@Post("/injuries/{id}/images", produces = [MULTIPART_FORM_DATA])
fun postImage(id: Long, body: MultipartBody, @Header authorization: String): ImageReference
}
The test
@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 error
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$27(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$6.run(SingleThreadEventExecutor.java:1044)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
Any clue about how to get rid of that error?
The client assumes method arguments are members of the body instead of each one representing the entire body. You can achieve the desired behavior by annotating the body argument in the client with @Body