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
290
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
WireMockでHTTPをモックしよう
2022/8/6 Java Do データアクセスについて聞きたい・話したい!
#javado
YutaSaito
August 05, 2022
More Decks by YutaSaito
See All by YutaSaito
依存関係のテストだけじゃないArchUnitのこんな使い方
yutasaito
2
320
JUnitで闘うレガシーコード改善
yutasaito
3
1k
Other Decks in Technology
See All in Technology
Introduction to Sansan Meishi Maker Development Engineer
sansan33
PRO
0
470
書籍『生成AIの安全性入門』の入門
wataoka
0
140
IHV like なユースケースへのOpenID Connect 関連仕様の適用事例
optim
0
410
dbt in Microsoft Fabric
ryomaru0825
0
310
Microsoft MVP プログラムを紹介するから目指す人増えてくれ
tsubakimoto_s
0
160
Does an AI Watermark Survive Translation?
machinetranslation
0
500
顧客の要望は2次情報である 〜アンテナを張るFDEの構造論〜
noriakioji
5
1.1k
Oracle AI Databaseデータベース・サービス: BaseDB/ExaDB-Dの可用性
oracle4engineer
PRO
1
990
Bill One 開発エンジニア 紹介資料
sansan33
PRO
7
20k
AIレビュー時代に必要なのは、SLOで引く撤退ライン
nobuoooo
0
160
When Token Pruning is Worse than Random: Understanding Visual Token Information in VLLMs
sansantech
PRO
0
200
いかに伝えるか 〜新卒エンジニアの教育のための、ライトノベル活用の一例
ikedon
1
120
Featured
See All Featured
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.1k
Ruling the World: When Life Gets Gamed
codingconduct
0
310
Making the Leap to Tech Lead
cromwellryan
135
10k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
AI: The stuff that nobody shows you
jnunemaker
PRO
9
950
How to Ace a Technical Interview
jacobian
281
24k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
580
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
490
Music & Morning Musume
bryan
47
7.3k
Product Roadmaps are Hard
iamctodd
55
12k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
510
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"); } }
ଞʹ৭ʑ͋Γ·͢ʂ
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠