Search code examples
spring-bootgroovyjunit5spockwiremock

Dynamic WireMock server in groovy test - Junit5


Regarding the article: https://wiremock.org/docs/junit-jupiter/

I tried doing my own server:

    @RegisterExtension
    static WireMockExtension wm1 = WireMockExtension.newInstance()
            .options(wireMockConfig().dynamicPort().dynamicHttpsPort())
            .build();

But i changed unknown method wireMockConfig() to new WireMockConfiguration()

In groovy test i get that an error Method threw 'groovy.lang.MissingPropertyException' exception. Property is getWm1.

Is this issue with spock and wiremock integration ?

Wiremock 2.33.0

Spock-core-2.2-groovy-3.0

springBootVersion=2.7.4

springCloudVersion=2021.0.3

Maybe this code does not work in integration test ?

EDIT: I was missing import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; IntelliJ did not find this import automatically. But this code does exactly the same - new WireMockConfiguration().


Solution

  • In addition to my comment, I also just saw your @RegisterExtension. Please note that the Spock 2.x test engine is a separate test engine on the JUnit 5 platform, it does not run on top of the Jupiter engine. Spock is a sibling rather than a child to Jupiter. Therefore, you cannot simply use Jupiter-specific annotations or extensions. You should rather do something like this, because WireMock does not provide its own Spock 2.x extension:

    package de.scrum_master.stackoverflow.q74613761
    
    import com.github.tomakehurst.wiremock.WireMockServer
    import spock.lang.Shared
    import spock.lang.Specification
    
    import static com.github.tomakehurst.wiremock.client.WireMock.*
    import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options
    
    class WireMockTest extends Specification {
      @Shared
      WireMockServer wiremockServer
    
      def setupSpec() {
        wiremockServer = new WireMockServer(options().dynamicHttpsPort())
        wiremockServer.start()
      }
    
      def cleanupSpec() {
        wiremockServer.stop()
      }
    
      def cleanup() {
        wiremockServer.resetAll()
      }
    
      def test() {
        stubFor(get("/api-1-thing").willReturn(ok()))
        stubFor(get("/api-2-stuff").willReturn(ok()))
    
        expect:
        wiremockServer.httpsPort()
      }
    }
    

    There is, however, a third-party Spock extension which enables you to use Jupiter annotations and also Jupiter extensions. I do not have any experience with it, but it seems to work for WireMock:

    package de.scrum_master.stackoverflow.q74613761
    
    import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer
    import com.github.tomakehurst.wiremock.junit5.WireMockExtension
    import org.junit.jupiter.api.extension.RegisterExtension
    import spock.lang.Specification
    
    import static com.github.tomakehurst.wiremock.client.WireMock.get
    import static com.github.tomakehurst.wiremock.client.WireMock.ok
    import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig
    
    /**
     * Needs <ul>
     *   <li><tt>com.github.tomakehurst:wiremock-jre8</tt>,</li>
     *   <li><tt>org.junit.jupiter:junit-jupiter-api</tt> in version fitting with Spock and WireMock,</li>
     *   <li><a href="https://github.com/xvik/spock-junit5"><tt>ru.vyarus:spock-junit5</tt></a> for being able to use Jupiter extensions in Spock 2.x.</li>
     * <ul>
     */
    class WireMockJupiterExtensionTest extends Specification {
      @RegisterExtension
      static WireMockExtension wm1 = WireMockExtension.newInstance()
        .options(wireMockConfig().dynamicPort().dynamicHttpsPort())
        .build()
      @RegisterExtension
      static WireMockExtension wm2 = WireMockExtension.newInstance()
        .options(wireMockConfig().dynamicPort().extensions(new ResponseTemplateTransformer(true)))
        .build()
    
      def test() {
        wm1.stubFor(get("/api-1-thing").willReturn(ok()))
        wm2.stubFor(get("/api-2-stuff").willReturn(ok()))
    
        expect:
        wm1.runtimeInfo.httpsPort
        wm1.port
      }
    }
    

    I would recommend not to rely on Jupiter-specific stuff, pulling it into Spock, as long as there are good alternatives like in this case, simply setting up WireMock by yourself. You can also put the configuration into a base spec and extend that base spec for your WireMock specs.