DEV Community

Cover image for Testing with WireMock Testcontainers
Roger Viñas Alcon
Roger Viñas Alcon

Posted on • Updated on

Testing with WireMock Testcontainers

In my previous two posts about testing with WireMock included in this series I used first @WireMockTest extension and later WireMock docker.

Recently a WireMock module for Testcontainers has been created by @onenashev 👏 so we can try it too! 🤩

Diagram

GitHub logo rogervinas / wiremock-testing

🤹 WireMock Testing

App test with WireMock Testcontainers module

Static stubs

We use Testcontainers JUnit5 extension to create two WireMock containers:

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()
  )
 }

Enter fullscreen mode Exit fullscreen mode
  • We can choose the container version, in this case wiremock:3.2.0.
  • We enable response templating adding the parameter --global-response-templating (see command line options).
  • We load mappings 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 and connecting it to the WireMock Admin API of the two WireMock containers:

@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()
 )
}
Enter fullscreen mode Exit fullscreen mode

Thanks and happy coding! 💙

Top comments (2)

Collapse
 
onenashev profile image
Oleg Nenashev

Thanks for the post and the updated demo, they look really good! Looking forward to releasing the version 1.0 of the WireMock module for Testcontainers Java and other language stacks. Whomever tries them out, any feedback will be appreciated!

Collapse
 
rogervinas profile image
Roger Viñas Alcon

🤖 Dependabot is waiting for that release! 😀 Thanks!