Testing with WireMock Testcontainers
Tags: wiremock, testcontainers, docker, tutorial
Published: 2023-11-10 08:03:14

In my previous two posts about testing with **WireMock** included in this series I used first [@WireMockTest extension](https://dev.to/rogervinas/testing-with-wiremocktest-3da0) and later [WireMock docker](https://dev.to/rogervinas/testing-with-wiremock-docker-2gh9).

Recently a [WireMock module for Testcontainers](https://github.com/wiremock/wiremock-testcontainers-java) has been created by @onenashev 👏 so we can try it too! 🤩

![Diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tswope2bkx3u1mfmkch0.png)

{% github rogervinas/wiremock-testing no-readme %}

* [App test with WireMock Testcontainers module](#app-test-with-wiremock-testcontainers-module)
  * [Static stubs](#static-stubs)
  * [Dynamic stubs](#dynamic-stubs)

## App test with WireMock Testcontainers module

### Static stubs

We use [Testcontainers JUnit5 extension](https://www.testcontainers.org/test_framework_integration/junit_5/) to create two **WireMock** containers:

```kotlin
class AppShouldWithWireMockTestcontainers {

 companion object {
  private const val name = "Ivy"

  @Container
  @JvmStatic
  val containerFoo = WireMockContainer("wiremock/wiremock:3.2.0")
   .withMappingFromJSON(File("wiremock/foo-api/mappings/foo-get.json").readText())
   .withCliArg("--global-response-templating")

  @Container
  @JvmStatic
  val containerBar = WireMockContainer("wiremock/wiremock:3.2.0")
   .withMappingFromJSON(File("wiremock/bar-api/mappings/bar-get.json").readText())
   .withCliArg("--global-response-templating")
  }

 @Test
 fun `call foo and bar`() {
  val fooApiUrl = "http://${containerFoo.host}:${containerFoo.port}"
  val barApiUrl = "http://${containerBar.host}:${containerBar.port}"

  val app = App(name, fooApiUrl, barApiUrl)

  assertThat(app.execute()).isEqualTo(
   """
   Hi! I am $name
   I called Foo and its response is Hello $name I am Foo!
   I called Bar and its response is Hello $name I am Bar!
   Bye!
   """.trimIndent()
  )
 }

```

* We can choose the container version, in this case `wiremock:3.2.0`.
* We enable [response templating](https://wiremock.org/docs/response-templating/) adding the parameter `--global-response-templating` (see [command line options](https://wiremock.org/docs/running-standalone/)).
* We load [mappings](https://wiremock.org/docs/stubbing/) from local json files.
* We obtain the dynamic ports that have been assigned to each container to build `fooApiUrl` and `barApiUrl`.

### Dynamic stubs

We can also configure our stubs programmatically using the [WireMock client](https://wiremock.org/docs/java-usage) and connecting it to the [WireMock Admin API](https://wiremock.org/docs/api/) of the two **WireMock** containers: 

```kotlin
@Test
fun `call foo an bar with dynamic stubs`() {
 val fooApiUrl = "http://${containerFoo.host}:${containerFoo.port}/dynamic"
 val barApiUrl = "http://${containerBar.host}:${containerBar.port}/dynamic"

 WireMock(containerFoo.host, containerFoo.port)
  .register(
   get(urlPathEqualTo("/dynamic/foo"))
    .withQueryParam("name", equalTo(name))
    .willReturn(ok().withBody("Hi $name I am Foo, how are you?"))
  )
 WireMock(containerBar.host, containerBar.port)
  .register(
   get(urlPathMatching("/dynamic/bar/$name"))
    .willReturn(ok().withBody("Hi $name I am Bar, nice to meet you!"))
  )

 val app = App(name, fooApiUrl, barApiUrl)

 assertThat(app.execute()).isEqualTo(
  """
   Hi! I am $name
   I called Foo and its response is Hi $name I am Foo, how are you?
   I called Bar and its response is Hi $name I am Bar, nice to meet you!
   Bye!
  """.trimIndent()
 )
}
```

Thanks and happy coding! 💙