Micronaut Gradle API测试因查询参数映射数据类失败
Micronaut Kotlin服务Spek测试请求失败(Bad Request)问题
我维护一个基于Micronaut Kotlin的遗留服务,基础功能正常:直接通过http://localhost:{port}/api/v1/test或带查询参数的http://localhost:{port}/api/v1/test?size=1&number=50&sort=ASC请求API,都能正常响应。但运行Spek测试时请求失败,抛出以下异常:
Bad Request
io.micronaut.http.client.exceptions.HttpClientResponseException: Bad Request
at io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.makeErrorFromRequestBody(DefaultHttpClient.java:2232)
测试时请求永远无法到达资源类中return HttpResponse.ok(mutableListOf("hello", "world"))这一行的断点。但如果把API方法的参数改成String类型:
fun listTestValues(@Parameter(required = false, `in` = ParameterIn.QUERY) pagingQuery: String)
调试器能正常停在对应的断点处。
核心代码结构
TestApi接口
interface TestApi { fun listTestValues(@Parameter(required = false, `in` = ParameterIn.QUERY) pagingQuery: PagingQueryWS): HttpResponse<List<*>> }
TestResource控制器
@Secured(SecurityRule.IS_AUTHENTICATED) @Controller( "/api/v1/test", consumes = [MediaType.APPLICATION_JSON], produces = [MediaType.APPLICATION_JSON] ) class TestResource: TestApi { @Get("{?pagingQuery*}") override fun listTestValues(pagingQuery: PagingQueryWS): HttpResponse<List<*>> { return HttpResponse.ok(mutableListOf("hello", "world")) } }
Spek测试类
class TestResourceUT: Spek({ Feature("Test Resource UT") { val applicationContext = ApplicationContext.builder().build().start() val embeddedServer = applicationContext.getBean(EmbeddedServer::class.java).start() val client = HttpClient.create(embeddedServer.url) Scenario("GET test api") { lateinit var returned: List<*> When("Responds successfully") { val request = HttpRequest.GET<List<String>>("/api/v1/test") returned = client .toBlocking() .retrieve(request, List::class.java) } Then("A List is returned with the found values") { assertThat(returned.size).isEqualTo(2) } } afterGroup { client.close() embeddedServer.close() } } })
分页参数类
@Introspected data class PagingQueryWS( override val number: Int = PagingQuery.DEFAULT_PAGE_NUMBER, override val size: Int = PagingQuery.DEFAULT_PAGE_SIZE, override val sort: String? = null ): PagingQuery interface PagingQuery { val number: Int val size: Int val sort: String? private fun getSort(): Sort { return sort ?.split(",") ?.map { val direction = it[0] val field = it.substring(1) if (direction == '-') { Order.desc(field) } else { Order.asc(field) } } ?.let { Sort.of(it) } ?: Sort.UNSORTED } // External pages are 1-indexed but internal are 0-indexed fun toPageable(): Pageable = Pageable.from(number - 1, size, getSort()) companion object { const val DEFAULT_PAGE_SIZE = 50 const val DEFAULT_PAGE_NUMBER = 1 } }
使用版本
- Kotlin 1.9.25
- Micronaut 3.9.7
- Spek 2.0.7
内容的提问来源于stack exchange,提问作者Kammryn Dancy
相关产品推荐
相关产品推荐

