Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WireMockでHTTPをモックしよう

 WireMockでHTTPをモックしよう

2022/8/6 Java Do データアクセスについて聞きたい・話したい!
#javado

YutaSaito

August 05, 2022
Tweet

More Decks by YutaSaito

Other Decks in Technology

Transcript

  1. !:VUB4BJUP
    8JSF.PDLͰ
    )551ΛϞοΫ͠Α͏

    View full-size slide

  2. ࣗݾ঺հ
    wಘҙྖҬ+BWB "84
    w޷͖ͳϓϩ໺ٿνʔϜ೔ϋϜ
    wग़਎౦๺
    w๺ւಓྺະ্཮ɻ͓͢͢Ίͷ؍ޫ஍΍ඒຯ͍͠͝൧Λڭ͑ͯԼ͍͞ʂ
    w5XJUUFS!:VUB4BJUP

    View full-size slide

  3. 8JSF.PDLͬͯʁ

    View full-size slide

  4. )551௨৴͕ൃੜ͢ΔίʔυͰͷࠔΓ͝ͱ
    w ৽͘͠"1*Λݺͼग़͢ඞཁ͕ੜ͕ͨ͡ɺ઀ଓઌͷγεςϜ͕·ͩ࡞ΒΕ͍ͯͳ
    ͍ͨΊίʔυ͕ಈ͔͘Θ͔Βͳ͍
    w ςετ؀ڥͰ઀ଓઌ"1*͕ظ଴ͨ͠஋Λฦͯ͘͠Εͳ͍ͨΊςετग़དྷͳ͍έ
    ʔε͕ଘࡏ͢Δ
    w "1*ͷ௨৴͕ඞཁͳϩδοΫͷςετίʔυΛॻ͚ͳ͍

    View full-size slide

  5. 8JSF.PDLͬͯʁ
    $MJFOU 4FSWJDF
    (&5IUUQFYBNQMFDPNIFMMP
    0,
    \lNFTTBHFzlIFMMPz^

    View full-size slide

  6. 8JSF.PDLͬͯʁ
    $MJFOU
    (&5IUUQFYBNQMFDPNIFMMP
    0,
    \lNFTTBHFzlIFMMPz^

    View full-size slide

  7. 8JSF.PDLͷಈ͔͠ํ

    View full-size slide

  8. 8JSF.PDLΛಈ͔͢ํ๏͸େ͖͘छྨ͋Γ·͢
    w +BWBͷϥΠϒϥϦΛར༻ͯ͠+6OJUͰىಈ͢Δ
    w +BSΛμ΢ϯϩʔυͯ͠ىಈ͢Δ
    w %PDLFSΠϝʔδΛىಈ͢Δ

    View full-size slide

  9. 8JSF.PDLΛಈ͔͢ํ๏͸େ͖͘छྨ͋Γ·͢
    w +BWBͷϥΠϒϥϦΛར༻ͯ͠+6OJUͰىಈ͢Δ
    w +BSΛμ΢ϯϩʔυͯ͠ىಈ͢Δ
    w %PDLFSΠϝʔδΛىಈ͢Δ

    View full-size slide

  10. +BWBͷϥΠϒϥϦΛར༻ͯ͠+6OJUͰىಈ͢Δ
    @WireMockTest


    public class HelloWireMockTest {


    @Test


    void helloΛฦ͢(WireMockRuntimeInfo wmRuntimeInfo) {


    stubFor(get("/hello").willReturn(okJson("{ \"message\": \"hello\" }")));


    String baseUrl = wmRuntimeInfo.getHttpBaseUrl();


    WebTestClient webTestClient = WebTestClient.bindToServer().baseUrl(baseUrl).build();


    webTestClient


    .get()


    .uri("hello")


    .accept(MediaType.APPLICATION_JSON)


    .exchange()


    .expectStatus()


    .isOk()


    .expectBody()


    .jsonPath("$.message")


    .isEqualTo("hello");


    }


    }


    View full-size slide

  11. 8JSF.PDLΛಈ͔͢ํ๏͸େ͖͘छྨ͋Γ·͢
    w +BWBͷϥΠϒϥϦΛར༻ͯ͠+6OJUͰىಈ͢Δ
    w +BSΛμ΢ϯϩʔυͯ͠ىಈ͢Δ
    w %PDLFSΠϝʔδΛىಈ͢Δ

    View full-size slide

  12. %PDLFSΠϝʔδΛىಈ͢Δ
    $ docker run -it --rm -p 8080:8080 wiremock/wiremock:2.33.2


    SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".


    SLF4J: Defaulting to no-operation (NOP) logger implementation


    SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.


    /$$ /$$ /$$ /$$ /$$ /$$


    | $$ /$ | $$|__/ | $$$ /$$$ | $$


    | $$ /$$$| $$ /$$ /$$$$$$ /$$$$$$ | $$$$ /$$$$ /$$$$$$ /$$$$$$$| $$ /$$


    | $$/$$ $$ $$| $$ /$$__ $$ /$$__ $$| $$ $$/$$ $$ /$$__ $$ /$$_____/| $$ /$$/


    | $$$$_ $$$$| $$| $$ \__/| $$$$$$$$| $$ $$$| $$| $$ \ $$| $$ | $$$$$$/


    | $$$/ \ $$$| $$| $$ | $$_____/| $$\ $ | $$| $$ | $$| $$ | $$_ $$


    | $$/ \ $$| $$| $$ | $$$$$$$| $$ \/ | $$| $$$$$$/| $$$$$$$| $$ \ $$


    |__/ \__/|__/|__/ \_______/|__/ |__/ \______/ \_______/|__/ \__/


    port: 8080


    enable-browser-proxying: false


    disable-banner: false


    no-request-journal: false


    verbose: false


    $ curl -X POST \


    —data '{ "request": { "url": "/hello", "method": "GET" }, "response": { "status": 200, "body": "{ \"message\": \"hello\"}
    ", "headers": { "Content-Type": "application/json" }}}' \


    http://localhost:8080/__admin/mappings/new


    $ curl http://localhost:8080/hello


    { "message": "hello"} %

    View full-size slide

  13. 8JSF.PDLͷ࢖͍ํ

    View full-size slide

  14. ελϒͷ࡞੒
    @WireMockTest


    public class BasicStubbing {


    @Test


    void stubing(WireMockRuntimeInfo wmRuntimeInfo) {


    stubFor(get("/hello").willReturn(aResponse().withStatus(200).withBody("Hello World!")));


    WebTestClient webTestClient =


    WebTestClient.bindToServer().baseUrl(wmRuntimeInfo.getHttpBaseUrl()).build();


    webTestClient


    .get()


    .uri("/hello")


    .exchange()


    .expectStatus()


    .isOk()


    .expectBody(String.class)


    .isEqualTo("Hello World!");


    }


    }


    View full-size slide

  15. ϦΫΤετϚονϯά
    63-ϚονϯάͰਖ਼نදݱΛར༻͢Δ
    @WireMockTest


    public class Matching {


    @Test


    void urlRegex(WireMockRuntimeInfo wmRuntimeInfo) {


    stubFor(get("/users/*").atPriority(10).willReturn(notFound()));


    stubFor(get(urlMatching("/users/(123|456)")).willReturn(okJson("{ \"message\": \"hello\" }")));


    WebTestClient webTestClient =


    WebTestClient.bindToServer().baseUrl(wmRuntimeInfo.getHttpBaseUrl()).build();


    webTestClient


    .get()


    .uri(uriBuilder -> uriBuilder.path("/users/{id}").build("123"))


    .exchange()


    .expectStatus()


    .isOk()


    .expectBody()


    .jsonPath("$.message")


    .isEqualTo("hello");


    webTestClient


    .get()


    .uri(uriBuilder -> uriBuilder.path("/users/{id}").build("789"))


    .exchange()


    .expectStatus()


    .isNotFound();


    }


    }

    View full-size slide

  16. ϦΫΤετϚονϯά
    ϦΫΤετͷଐੑΛར༻ͨ͠Ϛονϯά
    @WireMockTest


    public class Matching {


    @Test


    void header(WireMockRuntimeInfo wmRuntimeInfo) {


    stubFor(


    get("/users/123")


    .withHeader("Accept", equalTo("application/json"))


    .willReturn(okJson("{ \"message\": \"hello\" }")));


    stubFor(get("/users/123").withHeader("Accept", equalTo("text/plain")).willReturn(ok("hello")));


    WebTestClient webTestClient =


    WebTestClient.bindToServer().baseUrl(wmRuntimeInfo.getHttpBaseUrl()).build();


    webTestClient


    .get()


    .uri("/users/123")


    .accept(MediaType.APPLICATION_JSON)


    .exchange()


    .expectStatus()


    .isOk()


    .expectBody()


    .jsonPath("$.message")


    .isEqualTo("hello");


    webTestClient


    .get()


    .uri("/users/123")


    .accept(MediaType.TEXT_PLAIN)


    .exchange()


    .expectStatus()


    .isOk()


    .expectBody(String.class)


    .isEqualTo("hello");


    }


    }

    View full-size slide

  17. ϨεϙϯεςϯϓϨʔτ
    public class Templating {


    @RegisterExtension


    static WireMockExtension wireMockExtension =


    new WireMockExtension.Builder()


    .options(


    WireMockConfiguration.wireMockConfig()


    .dynamicPort()


    .extensions(new ResponseTemplateTransformer(true)))


    .build();


    @Test


    void templated() {


    wireMockExtension.stubFor(


    get("/templated")


    .willReturn(


    aResponse()


    .withBody("{{request.headers.X-Request-Id}}")


    .withTransformers("respones-template")));


    WebTestClient webTestClient =


    WebTestClient.bindToServer()


    .baseUrl(wireMockExtension.getRuntimeInfo().getHttpBaseUrl())


    .build();


    webTestClient


    .get()


    .uri("/templated")


    .header("X-Request-Id", "123")


    .exchange()


    .expectStatus()


    .isOk()


    .expectBody(String.class)


    .equals("123");


    }


    }


    View full-size slide

  18. ো֐ΛγϛϡϨʔγϣϯ
    @WireMockTest


    public class SimulationgFaults {


    @Test


    void timeout(WireMockRuntimeInfo wmRuntimeInfo) {


    stubFor(get("/delayed").willReturn(aResponse().withStatus(200).withFixedDelay(3000)));


    WebTestClient webTestClient =


    WebTestClient.bindToServer()


    .baseUrl(wmRuntimeInfo.getHttpBaseUrl())


    .responseTimeout(Duration.ofMillis(2000))


    .build();


    assertThatThrownBy(


    () -> {


    webTestClient.get().uri("/delayed").exchange().expectStatus().isOk();


    })


    .isInstanceOf(IllegalStateException.class)


    .hasMessageContaining("Timeout");


    }


    }


    View full-size slide

  19. ଞʹ΋৭ʑ͋Γ·͢ʂ

    View full-size slide

  20. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠

    View full-size slide