feature: #6: Add cucumber test for article routes

This commit is contained in:
2019-08-01 00:58:41 +02:00
parent 7acb2b3e40
commit 63a50dcb92
9 changed files with 213 additions and 12 deletions

25
test/RunCucumberTest.kt Normal file
View File

@@ -0,0 +1,25 @@
import cucumber.api.CucumberOptions
import cucumber.api.Scenario
import cucumber.api.java8.En
import cucumber.api.junit.Cucumber
import feature.Context
import io.ktor.server.testing.TestApplicationEngine
import io.ktor.server.testing.createTestEnvironment
import org.junit.runner.RunWith
import java.util.concurrent.TimeUnit
import feature.Context.Companion.current as contextCurrent
@RunWith(Cucumber::class)
@CucumberOptions(plugin = ["pretty"])
class RunCucumberTest: En {
init {
Before(-1) { scenario: Scenario ->
// config.database = "dc-projectg-test"
contextCurrent = Context(TestApplicationEngine(createTestEnvironment()) {}, scenario)
}
After { scenario: Scenario ->
contextCurrent.engine.stop(0L, 0L, TimeUnit.MILLISECONDS)
}
}
}

40
test/feature/Context.kt Normal file
View File

@@ -0,0 +1,40 @@
package feature
import cucumber.api.Scenario
import fr.dcproject.module
import io.ktor.application.Application
import io.ktor.server.testing.TestApplicationCall
import io.ktor.server.testing.TestApplicationEngine
import io.ktor.server.testing.TestApplicationRequest
class Context(
val engine: TestApplicationEngine,
val scenario: Scenario
) {
companion object {
lateinit var current: Context
}
init {
engine.start()
val moduleFunction: Application.() -> Unit = { module() }
val test: TestApplicationEngine.() -> Unit = {
moduleFunction(application)
}
engine.test()
}
var call: TestApplicationCall? = null
private val requestContextConfigurations: MutableList<TestApplicationRequest.() -> Unit> = mutableListOf()
fun setupRequest(testApplicationRequest: TestApplicationRequest) {
requestContextConfigurations.forEach {
it(testApplicationRequest)
}
}
fun setupNextRequests(requestContextConfiguration: TestApplicationRequest.() -> Unit) = requestContextConfigurations.add(requestContextConfiguration)
}
fun TestApplicationRequest.applyConfigurations() {
Context.current.setupRequest(this)
}

92
test/feature/Request.kt Normal file
View File

@@ -0,0 +1,92 @@
package feature
import com.google.gson.Gson
import cucumber.api.Scenario
import cucumber.api.java8.En
import io.cucumber.datatable.DataTable
import io.ktor.http.ContentType
import io.ktor.http.HttpHeaders
import io.ktor.http.HttpMethod
import io.ktor.http.HttpStatusCode
import io.ktor.server.testing.TestApplicationCall
import io.ktor.server.testing.TestApplicationEngine
import io.ktor.server.testing.setBody
import org.junit.jupiter.api.Assertions.assertEquals
import org.koin.test.KoinTest
import org.opentest4j.AssertionFailedError
import kotlin.test.asserter
import feature.Context.Companion.current as currentContext
class Request: En, KoinTest {
init {
Before { scenario: Scenario ->
}
After { scenario: Scenario ->
}
When("I send a {string} request to {string} with body:") { method: String, uri: String, body: String ->
val test: TestApplicationEngine.() -> Unit = {
currentContext.call = handleRequest {
applyConfigurations()
addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString())
this.method = HttpMethod.parse(method)
this.uri = uri
setBody(body)
}
}
currentContext.engine.test()
}
When("I send a {string} request to {string}") { method: String, uri: String ->
val test: TestApplicationEngine.() -> Unit = {
currentContext.call = handleRequest {
applyConfigurations()
addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString())
this.method = HttpMethod.parse(method.toUpperCase())
this.uri = uri
}
}
currentContext.engine.test()
}
Then("the response status code should be {int}") { statusCode: Int ->
val call: TestApplicationCall = currentContext.call ?: throw AssertionFailedError("No call", statusCode, null)
with(call) {
assertEquals(HttpStatusCode.fromValue(statusCode), response.status())
}
}
And("the response should contain:") { expected: DataTable ->
val call: TestApplicationCall = currentContext.call ?: throw AssertionFailedError("No call")
val p = call.response
val response = Gson().fromJson<List<Map<String, String>>>(p.content, List::class.java)
expected.asMap<String, String>(String::class.java, String::class.java).forEach { (key, value) ->
response.forEach {
if (it.containsKey(key)) {
assertEquals(it[key], value)
return@And
}
}
asserter.fail("The response not contain $key field")
}
}
And("the response should contain object:") { expected: DataTable ->
val call: TestApplicationCall = currentContext.call ?: throw AssertionFailedError("No call")
val p = call.response
val response = Gson().fromJson<Map<String, String>>(p.content, Map::class.java)
expected.asMap<String, String>(String::class.java, String::class.java).forEach { (key, value) ->
if (response.containsKey(key)) {
assertEquals(value, response[key])
return@And
}
asserter.fail("The response not contain $key field")
}
}
}
}