Skip to content

Commit

Permalink
Add minimal test case & server of post body
Browse files Browse the repository at this point in the history
Test case with body type fails, but unning the server acts as expected.
  • Loading branch information
plannigan committed May 22, 2020
1 parent 10f49e3 commit 71d820e
Show file tree
Hide file tree
Showing 2 changed files with 258 additions and 0 deletions.
118 changes: 118 additions & 0 deletions src/test/kotlin/MinimalServer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import com.fasterxml.jackson.annotation.*
import com.fasterxml.jackson.databind.ObjectMapper
import com.papsign.ktor.openapigen.OpenAPIGen
import com.papsign.ktor.openapigen.annotations.parameters.PathParam
import com.papsign.ktor.openapigen.route.*
import com.papsign.ktor.openapigen.route.path.normal.post
import com.papsign.ktor.openapigen.route.response.respond
import com.papsign.ktor.openapigen.schema.namer.DefaultSchemaNamer
import com.papsign.ktor.openapigen.schema.namer.SchemaNamer
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.features.CallLogging
import io.ktor.features.ContentNegotiation
import io.ktor.jackson.jackson
import io.ktor.request.receiveText
import io.ktor.response.respond
import io.ktor.routing.post
import io.ktor.routing.route
import io.ktor.routing.routing
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.slf4j.event.Level
import kotlin.reflect.KType

object MinimalServer {
data class SomeResponse(val value: String)
data class SomeBody @JsonCreator constructor(@JsonProperty("value") var value: String) {
override fun equals(other: Any?): Boolean {
val otherBody = other as? SomeBody ?: return false
return otherBody.value == value
}

override fun hashCode(): Int {
return value.hashCode()
}
}
data class StringParam(@PathParam("a simple string") val str: String)
@JvmStatic
fun main(args: Array<String>) {
embeddedServer(Netty, 8080, "localhost") {
//define basic OpenAPI info
install(OpenAPIGen) {
info {
version = "0.1"
title = "Test API"
description = "The Test API"
contact {
name = "Support"
email = "support@test.com"
}
}
server("http://localhost:8080/") {
description = "Test server"
}
replaceModule(DefaultSchemaNamer, object: SchemaNamer {
val regex = Regex("[A-Za-z0-9_.]+")
override fun get(type: KType): String {
return type.toString().replace(regex) { it.value.split(".").last() }.replace(Regex(">|<|, "), "_")
}
})
}

install(ContentNegotiation) {
jackson()
}
install(CallLogging) {
level = Level.DEBUG
}

routing {
route("/ktor/{str}") {
post {
println(call.parameters)
val bodyText = call.receiveText()
println(bodyText)
val objectMapper = ObjectMapper()
withContext(Dispatchers.IO) {
println(objectMapper.readValue(bodyText, SomeBody::class.java).value)
}
call.respond(SomeResponse("hello"))
}
}
}

apiRouting {
route("/openapi/any-body/{str}") {
post<StringParam, SomeResponse, Any> {
params, body ->
println(params)
val bodyText = pipeline.call.receiveText()
println(bodyText)
println(body) // Always Unit
val objectMapper = ObjectMapper()
withContext(Dispatchers.IO) {
println(objectMapper.readValue(bodyText, SomeBody::class.java).value)
}
respond(SomeResponse("hello"))
}
}

route("/openapi/typed-body/{str}") {
post<StringParam, SomeResponse, SomeBody> {
params, body ->
println(params)
// All ready received
// val bodyText = pipeline.call.receiveText()
// println(bodyText)
println(body)
println(body.value)
respond(SomeResponse("hello"))
}
}
}
}.start(true)
}
}
140 changes: 140 additions & 0 deletions src/test/kotlin/com/papsign/ktor/openapigen/MinimalTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package com.papsign.ktor.openapigen

import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.ObjectMapper
import com.papsign.ktor.openapigen.annotations.parameters.PathParam
import com.papsign.ktor.openapigen.route.apiRouting
import com.papsign.ktor.openapigen.route.path.normal.post
import com.papsign.ktor.openapigen.route.response.respond
import com.papsign.ktor.openapigen.route.route
import installJackson
import installOpenAPI
import io.ktor.application.Application
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.features.CallLogging
import io.ktor.http.HttpMethod
import io.ktor.request.receiveText
import io.ktor.response.respond
import io.ktor.routing.post
import io.ktor.routing.route
import io.ktor.routing.routing
import io.ktor.server.testing.TestApplicationEngine
import io.ktor.server.testing.handleRequest
import io.ktor.server.testing.setBody
import io.ktor.server.testing.withTestApplication
import org.junit.Assert.assertEquals
import org.junit.Test
import org.slf4j.event.Level


const val SOME_PARAM_ROUTE = "/test/{str}"
const val SOME_RESPONSE_VALUE = "test-response"
const val SOME_BODY_VALUE = "test-body"

class MinimalTest {
data class SomeResponse(val value: String)
data class SomeBody @JsonCreator constructor(@JsonProperty("value") var value: String) {
override fun equals(other: Any?): Boolean {
val otherBody = other as? SomeBody ?: return false
return otherBody.value == value
}

override fun hashCode(): Int {
return value.hashCode()
}
}
data class StringParam(@PathParam("a simple string") val str: String)

private val objectMapper = ObjectMapper()
private val someResponse = SomeResponse(SOME_RESPONSE_VALUE)
private val expectedResponseJson: String = objectMapper.writeValueAsString(someResponse)
private val expectedBody = SomeBody(SOME_BODY_VALUE)
private val someBodyJson: String = objectMapper.writeValueAsString(expectedBody)

@Test
fun testPost_bodyType_expectedBodyAndResponse() {
withTestApplication({
installModules()
apiRouting {
route(SOME_PARAM_ROUTE) {
post<StringParam, SomeResponse, SomeBody> {
params, body ->
println(params)
println(body)
assertEquals(expectedBody, body)
respond(someResponse)
}
}
}
}) {
sendVerifyPost()
}
}

@Test
fun testPost_noBodyType_expectedBodyAndResponse() {
withTestApplication({
installModules()
apiRouting {
route(SOME_PARAM_ROUTE) {
post<StringParam, SomeResponse, Any> {
params, body ->
val bodyText = pipeline.call.receiveText()
println(params)
println(body)
println(bodyText)
assertEquals(someBodyJson, bodyText)
assertEquals(expectedBody, objectMapper.readValue(bodyText, SomeBody::class.java))
// assertEquals(expectedBody, body) Always Unit
respond(someResponse)
}
}
}
}) {
sendVerifyPost()
}
}

@Test
fun testPost_ktorRouting_expectedBodyAndResponse() {
withTestApplication({
installModules()
routing {
route(SOME_PARAM_ROUTE) {
post {
val bodyText = call.receiveText()
println(call.parameters)
println(bodyText)
assertEquals(someBodyJson, bodyText)
assertEquals(expectedBody, objectMapper.readValue(bodyText, SomeBody::class.java))
call.respond(someResponse)
}
}
}
}) {
sendVerifyPost()
}
}

private fun TestApplicationEngine.sendVerifyPost() {
println("send request")
handleRequest(HttpMethod.Post, "/test/aaa"){
println("configure body")
setBody(someBodyJson)
}.apply {
println("post request")
assert(requestHandled)
assertEquals(expectedResponseJson, response.content)
}
}

private fun Application.installModules() {
installOpenAPI()
installJackson()
install(CallLogging) {
level = Level.DEBUG
}
}
}

0 comments on commit 71d820e

Please sign in to comment.