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
サービス間をテストするフレームワーク集
Search
Shin'ya Ueoka
December 15, 2021
Technology
390
0
Share
サービス間をテストするフレームワーク集
2021-12-15 開催 JJUGナイトセミナー「おうちで!ビール片手にLT大会!」でお話した資料です
https://jjug.doorkeeper.jp/events/129543
Shin'ya Ueoka
December 15, 2021
More Decks by Shin'ya Ueoka
See All by Shin'ya Ueoka
サイボウズ、プラットフォームエンジニアリング始めるってよ ― プラットフォームチームの事業貢献と組織アラインメントの強化
ueokande
0
160
開発インパクトを最大化!エンジニアが主導する組織づくりの実例
ueokande
0
90
エンジニアが主導できる組織づくり ー 製品と事業を進化させる体制へのシフト
ueokande
1
1.8k
どこで動かすか、誰が動かすか 〜 kintoneのインフラ基盤刷新と運用体制のシフト 〜
ueokande
0
360
kintone開発組織のDevOpsへの移り変わりと実践
ueokande
3
1.4k
運用できる開発組織の作り方 ― kintone開発組織のストーリー
ueokande
0
230
英語ができなかった自分達が、グローバルチーム立ち上げに挑戦!?
ueokande
1
1k
技術書典12協賛企業サイボウズゲストトーク
ueokande
0
330
kintone.comを支える技術
ueokande
0
240
Other Decks in Technology
See All in Technology
実装は速くなった、レビューはどうする? ― 自身のレビューをAIで再現させるサーヴァントエンジニアリングのすゝめ / Implementation got faster. So what about reviews? — An invitation to Servant Engineering: Recreating your own code reviews with AI
nrslib
6
3.8k
「コーディング」しない人のための Claude Code 入門 ChatGPT の次の一歩 — 業務に組み込む 育成・共有・自動化
rfdnxbro
2
1.2k
Terraformモジュールは、なぜ「魔境」化するのか
hayama17
1
190
個人最適 から 全体最適 へ AI情報共有会・AIギルド・AI-DLC で進める カンリーの組織展開
rfdnxbro
0
1.5k
Amazon Bedrock AgentCore ワークショップ JAWS UG TOHOKU / amazon-bedrock-agentcore-workshop-jawsug-tohoku-2026
gawa
8
240
Diagnosing performance problems without the guesswork
elenatanasoiu
0
160
Sony_KMP_Journey_KotlinConf2026
sony
2
210
2026.06.13_AI時代に事業会社が「SIer出身エンジニア」を求める理由 / Why Businesses Seek Engineers with a System Integrator Background in the AI Era
jumtech
0
500
イベントストーミングとKiroの仕様駆動開発で実現する要件の認識合わせプロセス
syobochim
7
1.2k
Platform Engineering as a Product: Criteria for Improvement and Multi-Tenant Design
kumorn5s
0
500
Databricks 月刊サービスアップデート 2026年05月号
tyosi1212
0
210
Dario Amodi『Policy on the AI Exponential』を理解する
nagatsu
0
180
Featured
See All Featured
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
390
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.2k
Testing 201, or: Great Expectations
jmmastey
46
8.2k
The agentic SEO stack - context over prompts
schlessera
0
790
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
160
Building AI with AI
inesmontani
PRO
1
1.1k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
360
Design in an AI World
tapps
1
220
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
260
Claude Code のすすめ
schroneko
67
230k
Utilizing Notion as your number one productivity tool
mfonobong
4
310
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
940
Transcript
αʔϏεؒΛςετ͢Δ ϑϨʔϜϫʔΫू αΠϘζגࣜձࣾ ্Ԭ ਅ (@ueokande) 2021-12-15. JJUGφΠτηϛφʔʮ͓͏ͪͰʂϏʔϧยखʹLTେձʂʯ
Me • αΠϘζגࣜձࣾ • άϩʔόϧ͚B2BαʔϏεͷ όοΫΤϯυΛ࡞͍ͬͯ·͢ • ݱͰKotlin +
Spring Boot͕ϝΠϯ 2
ຊͷ͓ • ෳαʔϏε͕ϓϩμΫτΛߏ͢Δ࣌ʢMicroservice, SOA, …ʣ • αʔϏεؒͷΓऔΓΛͲ͏ͬͯςετ͢Δ͔ʁ • REST API௨৴ͷݕূʹཱͭϑϨʔϜϫʔΫΛհ
3 αʔϏε" αʔϏε# )551ϦΫΤετ +40/
հϑϨʔϜϫʔΫ • Mockito … ΫϥΠΞϯτͷ࣮ͱϏδωεϩδοΫΛ • WireMock … ϞοΫαʔόʔΛཱͯͯΫϥΠΞϯτ࣮Λςετ •
Pact … αʔϏεؒ௨৴ͷAPIͷมߋΛݕ 4
Mockito • JavaͷΠϯλʔϑΣΠεɺΫϥεΛϞοΫ • ΫϥΠΞϯτ࣮ΛϞοΫͯ͠ϏδωεϩδοΫ୯ମΛςετ 5 αʔϏε" αʔϏε# )551ϦΫΤετ +40/
͜͜ΒΜͷςετ
Mockito͔͍͔ͭͨ • MockitoΛͬͯΫϥΠΞϯτ࣮ͷϞοΫΛهड़ • ϩδοΫ୯ମΛςε͠ɺΫϥΠΞϯτར༻͞Ε͔ͨݕূ 6 val client = mock<BClient>()
whenever(client.getItems()) .thenReturn(Arrays.asList(item1, …)) val logic = ItemLogic(bClient) val actual = sut.calc() assertEquals("...", actual) verify(bClient, times(1)).getItems() ϞοΫΫϥΠΞϯτͷ࡞ ϞοΫΫϥΠΞϯτΛͯ͠ ରΫϥεʢϏδωεϩδοΫʣͷݕূ MockΫϥΠΞϯτ͕ར༻͞Ε͔ͨݕূ ※ Kotlinͷίʔυྫ
WireMock • ϞοΫͷϨεϙϯεΛฦ͢HTTPαʔόʔΛཱͯΔ • HTTPαʔόʔϦΫΤετΛهͯ͠ظ͢ΔϦΫΤετ͔ݕূ 7 αʔϏε" αʔϏε# )551ϦΫΤετ +40/
͜͜ΒΜͷςετ
WireMock͔͍͔ͭͨ • ϦΫΤετʹର͢ΔϨεϙϯεΛఆٛͯ͠ϞοΫαʔόʔΛىಈ • ΫϥΠΞϯτ࣮ͱɺൃߦ͞ΕͨϦΫΤετ͕ਖ਼͍͔͠ݕূ 8 val server = WireMockServer(12345)
server.stubFor( WireMock.post(“/v1/item/1“) .willReturn(aResponse().withBody("{ ... }”))) server.start() val client = BClientImpl("127.0.0.1", 12345) List<Items> item = bClient.getItem(1L) assertEquals(10, actual.size) server.verify( postRequestedFor(urlPathEqualTo("/v1/items")) .withRequestBody(equalToJson("{ ... }")) ) ϞοΫαʔόʔͷ࡞ͱىಈ ϦΫΤετͷൃߦͱΓͷݕূ ࣮ߦ͞ΕͨϦΫΤετͷݕূ
Pact/Pact JVM • αʔϏεؒͷAPIͷৼΔ͍Λ୲อ͢ΔϑϨʔϜϫʔΫ 1. ίϯγϡʔϚʔɺར༻APIͷظ͢ΔϦΫΤετɾϨεϙϯεʢܖʣΛఆٛ 2. ίϯγϡʔϚʔɺΫϥΠΞϯτ࣮͕ܖͷ௨ΓʹৼΔ͏͔ݕূ 3. ϓϩόΠμʔɺܖͷϦΫΤετʹର͠ظͷϨεϙϯεΛฦ͔͢ݕূ
9 αʔϏε" $POTVNFS αʔϏε# 1SPWJFS ܖ ϞοΫ ϞοΫ ϦΫΤετ Ϩεϙϯε ϦΫΤετ Ϩεϙϯε ࡞ ݕূ ᶃ ᶄ ᶅ json
Pact JVM͍ํʛܖͷఆٛ • ίϯγϡʔϚʔଆ͕ར༻͢ΔAPIͷಈ࡞ΛDLSͰఆٛ 10 @Pact(provider = “service-b", consumer =
“service-a") fun getItemPact(builder: PactDslWithProvider): V4Pact { builder .given("item1 and item2 exist") .uponReceiving("get all items") .method(“GET”).matchPath(“/v1/item/1“) .willRespondWith().status(200).body( LambdaDsl.newJsonBody { it -> it.`object` { it.stringType(“name", “pen") it.numberType(“cost", 100) } } ) } ϦΫΤετʹର͢Δظ͢ΔϨεϙϯεΛఆٛ
Pact JVM͍ํʛίϯγϡʔϚʔͷݕূ • هड़ͨ͠ܖʹରͯ͠ΫϥΠΞϯτ࣮͕ਖ਼͘͠ৼΔ͏͔ݕূ • ϞοΫαʔόʔ͕ىಈͯ͠HTTPϦΫΤετΛهɾݕূ 11 @Test @PactTestFor(providerName =
“service-b", pactMethod = "getItemPact") fun getItem(mockServer: MockServer) { val client = BClientImpl(mockServer.getUrl()) val item = client.getItems(1L) assertEquals("pen", item.name) assertEquals(100, item.cost) }
Pact JVM͍ํʛϓϩόΠμʔͷݕূ • ϓϩόΠμʔ͕ܖ௨ΓͷϨεϙϯεΛฦ͔͢ݕূ • ܖΛͱʹPactϑϨʔϜϫʔΫ͕ࣗಈͰςετ 12 @ExtendWith(SpringExtension::class) @Provider(“service-b") @SpringBootTest(webEnvironment
= SpringBootTest.WebEnvironment.RANDOM_PORT) class ContractTest { @TestTemplate @ExtendWith(PactVerificationInvocationContextProvider::class) fun testTemplate( pact: Pact, interaction: Interaction, context: PactVerificationContext ) { context.verifyInteraction() } }
·ͱΊ • ਖ਼͍͠ϨΠϠʔͰϞοΫͯ͠ਖ਼͘͠ςετ • Mockito … αʔϏεͷΠϯλʔϑΣΠεͱ࣮ΫϥεΛ • WireMock …
ϦΫΤετɾϨεϙϯεΛϞοΫ • Pact … ৗʹมԽ͠ଓ͚ΔαʔϏεؒͷAPIͰഁյతมߋ͕ͳ͍͔νΣοΫ • ͍͠ϨΠϠʔςετɾࣗಈԽͯ҆͠৺ײΛಘΑ͏ 13