Skip to content

Commit 9a3eb62

Browse files
authored
Merge pull request #943 from diegotorrespy/master
KTLN-619: Added files and unit test for OpenAPI and Swagger
2 parents 23d0e3f + 9b49549 commit 9a3eb62

File tree

3 files changed

+182
-0
lines changed

3 files changed

+182
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.baeldung.openapi
2+
3+
import io.ktor.http.*
4+
import io.ktor.serialization.kotlinx.json.*
5+
import io.ktor.server.application.*
6+
import io.ktor.server.engine.*
7+
import io.ktor.server.netty.*
8+
import io.ktor.server.plugins.contentnegotiation.*
9+
import io.ktor.server.plugins.cors.routing.*
10+
import io.ktor.server.plugins.openapi.*
11+
import io.ktor.server.plugins.swagger.*
12+
import io.ktor.server.request.*
13+
import io.ktor.server.response.*
14+
import io.ktor.server.routing.*
15+
import io.swagger.codegen.v3.generators.html.StaticHtmlCodegen
16+
import kotlinx.serialization.Serializable
17+
import kotlinx.serialization.json.Json
18+
19+
@Serializable
20+
data class Product(val id: Int, val name: String, val price: Double)
21+
22+
fun main(args: Array<String>) {
23+
embeddedServer(Netty, port = 8080, module = Application::main).start(wait = true)
24+
}
25+
26+
fun Application.main() {
27+
val productStorage = mutableListOf<Product>()
28+
productStorage.addAll(
29+
arrayOf(
30+
Product(1, "Laptop", 999.99),
31+
Product(2, "Smartphone", 499.99)
32+
)
33+
)
34+
35+
install(ContentNegotiation) {
36+
json(Json {
37+
prettyPrint = true
38+
isLenient = true
39+
})
40+
}
41+
install(CORS) {
42+
anyHost()
43+
allowHeader(HttpHeaders.ContentType)
44+
}
45+
routing {
46+
get("/product/{id}") {
47+
val id = call.parameters["id"]
48+
val product: Product = productStorage.find { it.id == id!!.toInt() }!!
49+
call.respond(product)
50+
}
51+
52+
post("/product") {
53+
val product = call.receive<Product>()
54+
productStorage.add(product)
55+
call.respondText("Product saved successfully", status = HttpStatusCode.Created)
56+
}
57+
58+
swaggerUI(path = "swagger", swaggerFile = "openapi/documentation.yaml") {
59+
version = "4.15.5"
60+
}
61+
openAPI(path="openapi", swaggerFile = "openapi/documentation.yaml") {
62+
codegen = StaticHtmlCodegen()
63+
}
64+
}
65+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
openapi: "3.0.3"
2+
info:
3+
title: "Products API"
4+
description: "API to create and retrieve Products"
5+
version: "1.0.0"
6+
servers:
7+
- url: "http://0.0.0.0:8080"
8+
paths:
9+
/product:
10+
post:
11+
description: "Creates a new product"
12+
requestBody:
13+
description: "A JSON object that represents a product"
14+
required: true
15+
content:
16+
application/json:
17+
schema:
18+
$ref: "#/components/schemas/Product"
19+
responses:
20+
"201":
21+
description: "Created"
22+
content:
23+
text/plain:
24+
schema:
25+
type: "string"
26+
examples:
27+
Example#1:
28+
value: "Product saved successfully"
29+
/product/{id}:
30+
get:
31+
description: "Returns a product by the ID"
32+
parameters:
33+
- name: "id"
34+
in: "path"
35+
required: true
36+
schema:
37+
type: "string"
38+
responses:
39+
"200":
40+
description: "OK"
41+
content:
42+
'*/*':
43+
schema:
44+
$ref: "#/components/schemas/Product"
45+
components:
46+
schemas:
47+
Product:
48+
type: "object"
49+
properties:
50+
id:
51+
type: "integer"
52+
format: "int32"
53+
name:
54+
type: "string"
55+
price:
56+
type: "number"
57+
format: "double"
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import com.baeldung.openapi.Product
2+
import io.ktor.client.plugins.contentnegotiation.*
3+
import io.ktor.client.request.*
4+
import io.ktor.client.statement.*
5+
import io.ktor.http.*
6+
import io.ktor.serialization.kotlinx.json.*
7+
import io.ktor.server.testing.*
8+
import org.junit.After
9+
import java.io.File
10+
import kotlin.test.Test
11+
import kotlin.test.assertEquals
12+
13+
class ProductTests {
14+
@Test
15+
fun testSwaggerUIStatus() = testApplication {
16+
val response = client.get("/swagger")
17+
assertEquals(HttpStatusCode.OK, response.status)
18+
}
19+
20+
@Test
21+
fun testOpenApiStatus() = testApplication {
22+
val response = client.get("/openapi")
23+
assertEquals(HttpStatusCode.OK, response.status)
24+
}
25+
26+
@Test
27+
fun testGetProduct() = testApplication {
28+
val response = client.get("/product/1")
29+
assertEquals(
30+
"""
31+
{
32+
"id": 1,
33+
"name": "Laptop",
34+
"price": 999.99
35+
}
36+
""".trimIndent(), response.bodyAsText()
37+
)
38+
assertEquals(HttpStatusCode.OK, response.status)
39+
}
40+
41+
@Test
42+
fun testPostProduct() = testApplication {
43+
val client = createClient {
44+
install(ContentNegotiation) {
45+
json()
46+
}
47+
}
48+
val response = client.post("/product") {
49+
contentType(ContentType.Application.Json)
50+
setBody(Product(3, "Tablet", 299.99))
51+
}
52+
assertEquals("Product stored correctly", response.bodyAsText())
53+
assertEquals(HttpStatusCode.Created, response.status)
54+
}
55+
56+
@After
57+
fun deleteDocsDir() {
58+
File("docs").deleteRecursively()
59+
}
60+
}

0 commit comments

Comments
 (0)