Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
WireMockでHTTPをモックしよう
Search
YutaSaito
August 05, 2022
Technology
0
270
WireMockでHTTPをモックしよう
2022/8/6 Java Do データアクセスについて聞きたい・話したい!
#javado
YutaSaito
August 05, 2022
Tweet
Share
More Decks by YutaSaito
See All by YutaSaito
依存関係のテストだけじゃないArchUnitのこんな使い方
yutasaito
2
270
JUnitで闘うレガシーコード改善
yutasaito
3
950
Other Decks in Technology
See All in Technology
re:Inventに行くまでにやっておきたいこと
nagisa53
0
1.1k
The Twin Mandate of Observability
charity
1
450
AIの個性を理解し、指揮する
shoota
3
640
書籍『実践 Apache Iceberg』の歩き方
ishikawa_satoru
1
480
激動の時代を爆速リチーミングで乗り越えろ
sansantech
PRO
1
260
実践マルチモーダル検索!
shibuiwilliam
3
580
今日から使える AWS Step Functions 小技集 / AWS Step Functions Tips
kinunori
2
220
データエンジニアとして生存するために 〜界隈を盛り上げる「お祭り」が必要な理由〜 / data_summit_findy_Session_1
sansan_randd
1
980
なぜ新機能リリース翌日にモニタリング可能なのか? 〜リードタイム短縮とリソース問題を「自走」で改善した話〜 / data_summit_findy_Session_2
sansan_randd
1
120
SREのキャリアから経営に近づく - Enterprise Risk Managementを基に -
shonansurvivors
1
740
Mackerelにおけるインシデント対応とポストモーテム - 現場での工夫と学び
taxin
0
110
AI時代に必要なデータプラットフォームの要件とは by @Kazaneya_PR / 20251107
kazaneya
PRO
4
730
Featured
See All Featured
Unsuck your backbone
ammeep
671
58k
Embracing the Ebb and Flow
colly
88
4.9k
Art, The Web, and Tiny UX
lynnandtonic
303
21k
[RailsConf 2023] Rails as a piece of cake
palkan
57
6k
The World Runs on Bad Software
bkeepers
PRO
72
11k
Writing Fast Ruby
sferik
630
62k
The Cost Of JavaScript in 2023
addyosmani
55
9.1k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.5k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.2k
Stop Working from a Prison Cell
hatefulcrawdad
272
21k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
Reflections from 52 weeks, 52 projects
jeffersonlam
355
21k
Transcript
!:VUB4BJUP 8JSF.PDLͰ )551ΛϞοΫ͠Α͏
ࣗݾհ wಘҙྖҬ+BWB "84 w͖ͳϓϩٿνʔϜϋϜ wग़౦ wւಓྺະ্ɻ͓͢͢Ίͷ؍ޫඒຯ͍͠͝൧Λڭ͑ͯԼ͍͞ʂ w5XJUUFS!:VUB4BJUP
8JSF.PDLͬͯʁ
)551௨৴͕ൃੜ͢ΔίʔυͰͷࠔΓ͝ͱ w ৽͘͠"1*Λݺͼग़͢ඞཁ͕ੜ͕ͨ͡ɺଓઌͷγεςϜ͕·ͩ࡞ΒΕ͍ͯͳ ͍ͨΊίʔυ͕ಈ͔͘Θ͔Βͳ͍ w ςετڥͰଓઌ"1*͕ظͨ͠Λฦͯ͘͠Εͳ͍ͨΊςετग़དྷͳ͍έ ʔε͕ଘࡏ͢Δ w "1*ͷ௨৴͕ඞཁͳϩδοΫͷςετίʔυΛॻ͚ͳ͍
8JSF.PDLͬͯʁ $MJFOU 4FSWJDF (&5IUUQFYBNQMFDPNIFMMP 0, \lNFTTBHFzlIFMMPz^
8JSF.PDLͬͯʁ $MJFOU (&5IUUQFYBNQMFDPNIFMMP 0, \lNFTTBHFzlIFMMPz^
8JSF.PDLͷಈ͔͠ํ
8JSF.PDLΛಈ͔͢ํ๏େ͖͘छྨ͋Γ·͢ w +BWBͷϥΠϒϥϦΛར༻ͯ͠+6OJUͰىಈ͢Δ w +BSΛμϯϩʔυͯ͠ىಈ͢Δ w %PDLFSΠϝʔδΛىಈ͢Δ
8JSF.PDLΛಈ͔͢ํ๏େ͖͘छྨ͋Γ·͢ w +BWBͷϥΠϒϥϦΛར༻ͯ͠+6OJUͰىಈ͢Δ w +BSΛμϯϩʔυͯ͠ىಈ͢Δ w %PDLFSΠϝʔδΛىಈ͢Δ
+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"); } }
8JSF.PDLΛಈ͔͢ํ๏େ͖͘छྨ͋Γ·͢ w +BWBͷϥΠϒϥϦΛར༻ͯ͠+6OJUͰىಈ͢Δ w +BSΛμϯϩʔυͯ͠ىಈ͢Δ w %PDLFSΠϝʔδΛىಈ͢Δ
%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"} %
8JSF.PDLͷ͍ํ
ελϒͷ࡞ @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!"); } }
ϦΫΤετϚονϯά 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(); } }
ϦΫΤετϚονϯά ϦΫΤετͷଐੑΛར༻ͨ͠Ϛονϯά @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"); } }
ϨεϙϯεςϯϓϨʔτ 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"); } }
োΛγϛϡϨʔγϣϯ @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"); } }
ଞʹ৭ʑ͋Γ·͢ʂ
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠