Skip to content

Commit

Permalink
add snippet for »Spring« (REST) HTTP Interface
Browse files Browse the repository at this point in the history
  • Loading branch information
agebhar1 committed Jul 21, 2024
1 parent 8cc40d9 commit 0a5be39
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 0 deletions.
20 changes: 20 additions & 0 deletions spring-boot/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,19 @@
<diktat.version>1.2.5</diktat.version>
<!-- dependency version(s) -->
<junit-pioneer.version>2.2.0</junit-pioneer.version>
<wiremock-testcontainers-module.version>1.0-alpha-13</wiremock-testcontainers-module.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.wiremock.integrations.testcontainers</groupId>
<artifactId>wiremock-testcontainers-module</artifactId>
<version>${wiremock-testcontainers-module.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<!-- scope: compile -->
<dependency>
Expand Down Expand Up @@ -58,6 +69,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-file</artifactId>
Expand Down Expand Up @@ -114,6 +129,11 @@
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wiremock.integrations.testcontainers</groupId>
<artifactId>wiremock-testcontainers-module</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package io.github.agebhar1.snippets

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.test.context.junit.jupiter.SpringExtension
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.support.WebClientAdapter
import org.springframework.web.service.annotation.DeleteExchange
import org.springframework.web.service.annotation.GetExchange
import org.springframework.web.service.annotation.HttpExchange
import org.springframework.web.service.annotation.PostExchange
import org.springframework.web.service.invoker.HttpServiceProxyFactory
import org.testcontainers.containers.output.Slf4jLogConsumer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
import org.wiremock.integrations.testcontainers.WireMockContainer

data class ToDo(
val id: String,
val title: String,
val completed: Boolean
)

@HttpExchange(url = "/todos", accept = ["application/json"], contentType = "application/json")
interface ToDosService {
@GetExchange
fun getAll(): List<ToDo>

@GetExchange("/{id}")
fun getById(@PathVariable id: String): ToDo?

@PostExchange
fun save(@RequestBody todo: ToDo): ToDo

@DeleteExchange("/{id}")
fun delete(@PathVariable id: String)
}

@ExtendWith(SpringExtension::class)
@Testcontainers
class HttpExchangeTest(@Autowired private val client: ToDosService) {
@Test
fun `(service) client should get all ToDo items`() {
assertThat(client.getAll())
.containsExactly(
ToDo(id = "199d25ae-42e2-4cc8-9a97-571a46e25689", title = "Item #1", completed = true),
ToDo(id = "d2db635a-27e4-4a63-9d07-1a19aa52ace8", title = "Item #2", completed = false),
ToDo(id = "dc800874-bad2-4aeb-ada6-ca8f7630c6a2", title = "Item #3", completed = false)
)
}

@Test
fun `(service) client should get ToDo item by Id`() {
assertThat(client.getById("199d25ae-42e2-4cc8-9a97-571a46e25689"))
.isEqualTo(
ToDo(id = "199d25ae-42e2-4cc8-9a97-571a46e25689", title = "Item #1", completed = true)
)
}

@Test
fun `(service) client should save ToDo item`() {
val todo = ToDo(id = "34c93fba-da84-45f6-921a-9ab6322d9ee0", title = "Item #4", completed = false)
assertThat(client.save(todo)).isEqualTo(todo)
}

@Test
fun `(service) client should delete ToDo item by Id`() {
client.delete("199d25ae-42e2-4cc8-9a97-571a46e25689")
}

@TestConfiguration
class Configuration {
@Bean
fun client(): ToDosService {
val webClient = WebClient.builder().baseUrl(wm.baseUrl).build()
val factory = HttpServiceProxyFactory
.builderFor(WebClientAdapter.create(webClient))
.build()

return factory.createClient(ToDosService::class.java)
}
}

companion object {
private val logger: Logger = LoggerFactory.getLogger(HttpExchangeTest::class.java)

@Container
val wm: WireMockContainer = WireMockContainer("wiremock/wiremock:3.9.0-1")
.withLogConsumer(Slf4jLogConsumer(logger).withSeparateOutputStreams())
.withMappingFromResource("todo", "wiremock/todo-stubs.json")
}
}
125 changes: 125 additions & 0 deletions spring-boot/src/test/resources/wiremock/todo-stubs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
{
"mappings": [
{
"id": "ff4d49aa-5e41-42fe-8a65-79ceb56f6558",
"request": {
"urlPath": "/todos",
"method": "GET"
},
"response": {
"status": 200,
"jsonBody": [
{
"id": "199d25ae-42e2-4cc8-9a97-571a46e25689",
"title": "Item #1",
"completed": true
},
{
"id": "d2db635a-27e4-4a63-9d07-1a19aa52ace8",
"title": "Item #2",
"completed": false
},
{
"id": "dc800874-bad2-4aeb-ada6-ca8f7630c6a2",
"title": "Item #3",
"completed": false
}
],
"headers": {
"Content-Type": "application/json"
}
}
},
{
"id": "44ba9592-01a7-4402-8cd1-04526b0e3d5f",
"request": {
"urlPath": "/todos/199d25ae-42e2-4cc8-9a97-571a46e25689",
"method": "GET"
},
"response": {
"status": 200,
"jsonBody": {
"id": "199d25ae-42e2-4cc8-9a97-571a46e25689",
"title": "Item #1",
"completed": true
},
"headers": {
"Content-Type": "application/json"
}
}
},
{
"id": "22f08c71-5d3f-4d37-bcc8-8f994942f79c",
"request": {
"urlPath": "/todos/d2db635a-27e4-4a63-9d07-1a19aa52ace8",
"method": "GET"
},
"response": {
"status": 200,
"jsonBody": {
"id": "d2db635a-27e4-4a63-9d07-1a19aa52ace8",
"title": "Item #2",
"completed": false
},
"headers": {
"Content-Type": "application/json"
}
}
},
{
"id": "0d464423-94f8-491b-969e-954aee74d35b",
"request": {
"urlPath": "/todos/dc800874-bad2-4aeb-ada6-ca8f7630c6a2",
"method": "GET"
},
"response": {
"status": 200,
"jsonBody": {
"id": "dc800874-bad2-4aeb-ada6-ca8f7630c6a2",
"title": "Item #3",
"completed": false
},
"headers": {
"Content-Type": "application/json"
}
}
},
{
"id": "e5a243d5-e5d4-4230-9784-8a301492e8c0",
"request": {
"urlPath": "/todos",
"method": "POST",
"bodyPatterns": [
{
"equalToJson": {
"id": "34c93fba-da84-45f6-921a-9ab6322d9ee0",
"title": "Item #4",
"completed": false
}
}
]
},
"response": {
"status": 201,
"jsonBody": {
"id": "34c93fba-da84-45f6-921a-9ab6322d9ee0",
"title": "Item #4",
"completed": false
},
"headers": {
"Content-Type": "application/json"
}
}
},
{
"id": "17e883e8-9147-4483-8945-36105a0c1304",
"request": {
"urlPath": "/todos/199d25ae-42e2-4cc8-9a97-571a46e25689",
"method": "DELETE"
},
"response": {
"status": 204
}
}
]
}

0 comments on commit 0a5be39

Please sign in to comment.