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

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

Shin'ya Ueoka
December 15, 2021

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

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

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େձʂʯ

    View full-size slide

  2. Me
    • αΠϘ΢ζגࣜձࣾ


    • άϩʔόϧ޲͚B2BαʔϏεͷ

    όοΫΤϯυΛ࡞͍ͬͯ·͢


    • ݱ৔Ͱ͸Kotlin + Spring Boot͕ϝΠϯ
    2

    View full-size slide

  3. ຊ೔ͷ͓࿩
    • ෳ਺αʔϏε͕ϓϩμΫτΛߏ੒͢Δ࣌୅ʢMicroservice, SOA, …ʣ


    • αʔϏεؒͷ΍ΓऔΓΛͲ͏΍ͬͯςετ͢Δ͔ʁ


    • REST API௨৴ͷݕূʹ໾ཱͭϑϨʔϜϫʔΫΛ঺հ
    3
    αʔϏε" αʔϏε#
    )551ϦΫΤετ
    +40/

    View full-size slide

  4. ঺հϑϨʔϜϫʔΫ
    • Mockito … ΫϥΠΞϯτͷ࣮૷ͱϏδωεϩδοΫΛ෼཭


    • WireMock … ϞοΫαʔόʔΛཱͯͯΫϥΠΞϯτ࣮૷Λςετ


    • Pact … αʔϏεؒ௨৴ͷAPIͷมߋΛݕ஌
    4

    View full-size slide

  5. Mockito
    • JavaͷΠϯλʔϑΣΠεɺΫϥεΛϞοΫ


    • ΫϥΠΞϯτ࣮૷ΛϞοΫͯ͠ϏδωεϩδοΫ୯ମΛςετ
    5
    αʔϏε" αʔϏε#
    )551ϦΫΤετ
    +40/
    ͜͜Β΁Μͷςετ

    View full-size slide

  6. Mockito͔͍͔ͭͨ
    • MockitoΛ࢖ͬͯΫϥΠΞϯτ࣮૷ͷϞοΫΛهड़


    • ϩδοΫ୯ମΛςε͠ɺΫϥΠΞϯτར༻͞Ε͔ͨݕূ
    6
    val client = mock()
    whenever(client.getItems())
    .thenReturn(Arrays.asList(item1, …))
    val logic = ItemLogic(bClient)
    val actual = sut.calc()
    assertEquals("...", actual)
    verify(bClient, times(1)).getItems()
    ϞοΫΫϥΠΞϯτͷ࡞੒
    ϞοΫΫϥΠΞϯτΛ౉ͯ͠

    ର৅ΫϥεʢϏδωεϩδοΫʣͷݕূ
    MockΫϥΠΞϯτ͕ར༻͞Ε͔ͨݕূ
    ※ Kotlinͷίʔυྫ

    View full-size slide

  7. WireMock
    • ϞοΫͷϨεϙϯεΛฦ͢HTTPαʔόʔΛཱͯΔ


    • HTTPαʔόʔ͸ϦΫΤετΛه࿥ͯ͠ظ଴͢ΔϦΫΤετ͔ݕূ
    7
    αʔϏε" αʔϏε#
    )551ϦΫΤετ
    +40/
    ͜͜Β΁Μͷςετ

    View full-size slide

  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 item = bClient.getItem(1L)
    assertEquals(10, actual.size)
    server.verify(
    postRequestedFor(urlPathEqualTo("/v1/items"))
    .withRequestBody(equalToJson("{ ... }"))

    )
    ϞοΫαʔόʔͷ࡞੒ͱىಈ
    ϦΫΤετͷൃߦͱ໭Γ஋ͷݕূ
    ࣮ߦ͞ΕͨϦΫΤετͷݕূ

    View full-size slide

  9. Pact/Pact JVM
    • αʔϏεؒͷAPIͷৼΔ෣͍Λ୲อ͢ΔϑϨʔϜϫʔΫ


    1. ίϯγϡʔϚʔ͸ɺར༻APIͷظ଴͢ΔϦΫΤετɾϨεϙϯεʢܖ໿ʣΛఆٛ


    2. ίϯγϡʔϚʔ͸ɺΫϥΠΞϯτ࣮૷͕ܖ໿ͷ௨ΓʹৼΔ෣͏͔ݕূ


    3. ϓϩόΠμʔ͸ɺܖ໿ͷϦΫΤετʹର͠ظ଴ͷϨεϙϯεΛฦ͔͢ݕূ
    9
    αʔϏε"

    $POTVNFS
    αʔϏε#

    1SPWJFS
    ܖ໿
    ϞοΫ ϞοΫ
    ϦΫΤετ
    Ϩεϙϯε
    ϦΫΤετ
    Ϩεϙϯε
    ࡞੒ ݕূ

    ᶄ ᶅ
    json

    View full-size slide

  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)
    }
    }
    )
    }
    ϦΫΤετʹର͢Δظ଴͢ΔϨεϙϯεΛఆٛ

    View full-size slide

  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)
    }

    View full-size slide

  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()
    }
    }

    View full-size slide

  13. ·ͱΊ
    • ਖ਼͍͠ϨΠϠʔͰϞοΫͯ͠ਖ਼͘͠ςετ


    • Mockito … αʔϏε಺ͷΠϯλʔϑΣΠεͱ࣮૷ΫϥεΛ෼཭


    • WireMock … ϦΫΤετɾϨεϙϯεΛϞοΫ


    • Pact … ৗʹมԽ͠ଓ͚ΔαʔϏεؒͷAPIͰഁյతมߋ͕ͳ͍͔νΣοΫ


    • ೉͍͠ϨΠϠʔ΋ςετɾࣗಈԽͯ҆͠৺ײΛಘΑ͏
    13

    View full-size slide