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

サービス間をテストするフレームワーク集

 サービス間をテストするフレームワーク集

2021-12-15 開催 JJUGナイトセミナー「おうちで!ビール片手にLT大会!」でお話した資料です
https://jjug.doorkeeper.jp/events/129543

C51ed1e43b09bfbbb09eead09f803aea?s=128

Shin'ya Ueoka

December 15, 2021
Tweet

More Decks by Shin'ya Ueoka

Other Decks in Technology

Transcript

  1. αʔϏεؒΛςετ͢Δ ϑϨʔϜϫʔΫू αΠϘ΢ζגࣜձࣾ ্Ԭ ਅ໵ (@ueokande) 2021-12-15. JJUGφΠτηϛφʔʮ͓͏ͪͰʂϏʔϧยखʹLTେձʂʯ

  2. Me • αΠϘ΢ζגࣜձࣾ • άϩʔόϧ޲͚B2BαʔϏεͷ 
 όοΫΤϯυΛ࡞͍ͬͯ·͢ • ݱ৔Ͱ͸Kotlin +

    Spring Boot͕ϝΠϯ 2
  3. ຊ೔ͷ͓࿩ • ෳ਺αʔϏε͕ϓϩμΫτΛߏ੒͢Δ࣌୅ʢMicroservice, SOA, …ʣ • αʔϏεؒͷ΍ΓऔΓΛͲ͏΍ͬͯςετ͢Δ͔ʁ • REST API௨৴ͷݕূʹ໾ཱͭϑϨʔϜϫʔΫΛ঺հ

    3 αʔϏε" αʔϏε# )551ϦΫΤετ +40/
  4. ঺հϑϨʔϜϫʔΫ • Mockito … ΫϥΠΞϯτͷ࣮૷ͱϏδωεϩδοΫΛ෼཭ • WireMock … ϞοΫαʔόʔΛཱͯͯΫϥΠΞϯτ࣮૷Λςετ •

    Pact … αʔϏεؒ௨৴ͷAPIͷมߋΛݕ஌ 4
  5. Mockito • JavaͷΠϯλʔϑΣΠεɺΫϥεΛϞοΫ • ΫϥΠΞϯτ࣮૷ΛϞοΫͯ͠ϏδωεϩδοΫ୯ମΛςετ 5 αʔϏε" αʔϏε# )551ϦΫΤετ +40/

    ͜͜Β΁Μͷςετ
  6. 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ͷίʔυྫ
  7. WireMock • ϞοΫͷϨεϙϯεΛฦ͢HTTPαʔόʔΛཱͯΔ • HTTPαʔόʔ͸ϦΫΤετΛه࿥ͯ͠ظ଴͢ΔϦΫΤετ͔ݕূ 7 αʔϏε" αʔϏε# )551ϦΫΤετ +40/

    ͜͜Β΁Μͷςετ
  8. 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("{ ... }"))
 ) ϞοΫαʔόʔͷ࡞੒ͱىಈ ϦΫΤετͷൃߦͱ໭Γ஋ͷݕূ ࣮ߦ͞ΕͨϦΫΤετͷݕূ
  9. Pact/Pact JVM • αʔϏεؒͷAPIͷৼΔ෣͍Λ୲อ͢ΔϑϨʔϜϫʔΫ 1. ίϯγϡʔϚʔ͸ɺར༻APIͷظ଴͢ΔϦΫΤετɾϨεϙϯεʢܖ໿ʣΛఆٛ 2. ίϯγϡʔϚʔ͸ɺΫϥΠΞϯτ࣮૷͕ܖ໿ͷ௨ΓʹৼΔ෣͏͔ݕূ 3. ϓϩόΠμʔ͸ɺܖ໿ͷϦΫΤετʹର͠ظ଴ͷϨεϙϯεΛฦ͔͢ݕূ

    9 αʔϏε" 
 $POTVNFS αʔϏε# 
 1SPWJFS ܖ໿ ϞοΫ ϞοΫ ϦΫΤετ Ϩεϙϯε ϦΫΤετ Ϩεϙϯε ࡞੒ ݕূ ᶃ ᶄ ᶅ json
  10. 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) } } ) } ϦΫΤετʹର͢Δظ଴͢ΔϨεϙϯεΛఆٛ
  11. 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) }
  12. 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() } }
  13. ·ͱΊ • ਖ਼͍͠ϨΠϠʔͰϞοΫͯ͠ਖ਼͘͠ςετ • Mockito … αʔϏε಺ͷΠϯλʔϑΣΠεͱ࣮૷ΫϥεΛ෼཭ • WireMock …

    ϦΫΤετɾϨεϙϯεΛϞοΫ • Pact … ৗʹมԽ͠ଓ͚ΔαʔϏεؒͷAPIͰഁյతมߋ͕ͳ͍͔νΣοΫ • ೉͍͠ϨΠϠʔ΋ςετɾࣗಈԽͯ҆͠৺ײΛಘΑ͏ 13