Skip to content

Commit

Permalink
Add ApiTest written using Junit to demonstrate Specmatic dynamic mock…
Browse files Browse the repository at this point in the history
…ing feature
  • Loading branch information
yogeshnikam671 committed Aug 2, 2024
1 parent bab3ee1 commit a67a57b
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 11 deletions.
152 changes: 152 additions & 0 deletions src/test/kotlin/com/component/orders/ApiTests.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package com.component.orders

import com.fasterxml.jackson.databind.ObjectMapper
import io.specmatic.kafka.mock.KafkaMock
import io.specmatic.kafka.mock.model.Expectation
import io.specmatic.stub.ContractStub
import io.specmatic.stub.createStub
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.web.client.TestRestTemplate
import org.springframework.http.HttpEntity
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.test.context.junit.jupiter.SpringExtension
import java.io.File

//@ExtendWith(SpringExtension::class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class ApiTests {
companion object {
private lateinit var httpStub: ContractStub
private lateinit var kafkaMock: KafkaMock

private const val STUB_PORT = 8090

@BeforeAll
@JvmStatic
fun setUp() {
// Start Specmatic Http Stub
httpStub = createStub("localhost", STUB_PORT, strict = true)

// Start kafka mock
kafkaMock = KafkaMock.startInMemoryBroker("localhost", 9092)
}

@AfterAll
@JvmStatic
fun tearDown() {
// Shutdown Specmatic Http Stub
httpStub.close()

// Stop kafka mock
kafkaMock.stop()
}
}

@Autowired
private lateinit var restTemplate: TestRestTemplate

private fun setExpectations(expectation: String) {
val url = "http://localhost:$STUB_PORT/_specmatic/expectations"
val response: ResponseEntity<String> = restTemplate.exchange(
url,
HttpMethod.POST,
HttpEntity(expectation.toMap()),
String::class.java
)
assert(response.statusCode == HttpStatus.OK)
}

@Test
fun `should search for available products`() {
val expectation = File("src/test/resources/stub_products_200.json").readText()
setExpectations(expectation)

val url = "http://localhost:8080/findAvailableProducts?type=gadget"
val headers = HttpHeaders().apply {
set("pageSize", "10")
}
val response = restTemplate.exchange(
url,
HttpMethod.GET,
HttpEntity<String>(headers),
List::class.java
)

assert(response.statusCode == HttpStatus.OK)

val expectedResponse = expectation.toMap()["http-response"] as Map<String, Any>
val expectedResponseBody = expectedResponse["body"] as List<Map<String, Any>>
val actualResponseBody = response.body as List<Map<String, Any>>
assertThat(actualResponseBody).isEqualTo(expectedResponseBody)
}

@Test
fun `should return 503 (SERVICE_UNAVAILABLE) status if backend service is down`() {
val expectation = File("src/test/resources/stub timeout.json").readText()
setExpectations(expectation)
val url = "http://localhost:8080/findAvailableProducts?type=other"
val headers = HttpHeaders().apply {
set("pageSize", "10")
}
val response = restTemplate.exchange(
url,
HttpMethod.GET,
HttpEntity<String>(headers),
String::class.java
)

assert(response.statusCode == HttpStatus.SERVICE_UNAVAILABLE)
}

@Test
fun `should create order`() {
val expectation = """
{
"http-request": {
"method": "POST",
"path": "/orders",
"headers": {
"Authenticate": "API-TOKEN-SPEC"
},
"body": {
"productid": 10,
"count": 1,
"status": "pending"
}
},
"http-response": {
"status": 200,
"body": {
"id": 10
},
"status-text": "OK"
}
}
""".trimIndent()
setExpectations(expectation)

val response = restTemplate.exchange(
"http://localhost:8080/orders",
HttpMethod.POST,
HttpEntity(mapOf("productid" to 10, "count" to 1)),
Map::class.java
)

assert(response.statusCode == HttpStatus.CREATED)
assertThat(response.body["id"] as Int).isEqualTo(10)
}

private fun String.toMap(): Map<*, *> {
return ObjectMapper().readValue(this, Map::class.java)
}
}
13 changes: 2 additions & 11 deletions src/test/kotlin/com/component/orders/contract/ContractTests.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.component.orders.contract

import com.component.orders.Application
import io.specmatic.kafka.mock.KafkaMock
import io.specmatic.kafka.mock.model.Expectation
import io.specmatic.stub.ContractStub
Expand All @@ -9,13 +8,12 @@ import io.specmatic.test.SpecmaticContractTest
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll
import org.springframework.boot.SpringApplication
import org.springframework.context.ConfigurableApplicationContext
import org.springframework.boot.test.context.SpringBootTest

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class ContractTests : SpecmaticContractTest {

companion object {
private lateinit var context: ConfigurableApplicationContext
private lateinit var httpStub: ContractStub
private lateinit var kafkaMock: KafkaMock
private const val APPLICATION_HOST = "localhost"
Expand All @@ -42,18 +40,11 @@ class ContractTests : SpecmaticContractTest {
// Start Specmatic Kafka Mock and set the expectations
kafkaMock = KafkaMock.startInMemoryBroker(KAFKA_MOCK_HOST, KAFKA_MOCK_PORT)
kafkaMock.setExpectations(listOf(Expectation("product-queries", EXPECTED_NUMBER_OF_MESSAGES)))

// Start Springboot application
val springApp = SpringApplication(Application::class.java)
context = springApp.run()
}

@JvmStatic
@AfterAll
fun tearDown() {
// Shutdown Springboot application
context.stop()

// Shutdown Specmatic Http Stub
httpStub.close()

Expand Down

0 comments on commit a67a57b

Please sign in to comment.