RestAssured

์ƒํ™ฉ

  • ํŒ€ ์›น ์„œ๋น„์Šค API ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ํ•˜๋ฉด์„œ Spring MockMvc๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ด์™”์Šต๋‹ˆ๋‹ค.

MockMvc์˜ ํ•œ๊ณ„

  • MockMvc๋Š” Spring MVC์˜ ์ปจํŠธ๋กค๋Ÿฌ ํ…Œ์ŠคํŠธ์— ํŠนํ™”๋˜์–ด ์žˆ์ง€๋งŒ, ์‹ค์ œ HTTP ์š”์ฒญ๊ณผ ์‘๋‹ต์˜ ํ๋ฆ„์„ ์™„์ „ํžˆ ๋ชจ๋ฐฉํ•˜์ง€๋Š” ๋ชปํ•ฉ๋‹ˆ๋‹ค.

  • ๋ณต์žกํ•œ ์„ค์ •๊ณผ ์ƒ๋Œ€์ ์œผ๋กœ ๋‚ฎ์€ ๊ฐ€๋…์„ฑ์œผ๋กœ ์ธํ•ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ์œ ์ง€ ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ

@Sql(statements = "insert into organization (title) values ('eojjeogojeojjeogo')")
@DisplayName("๋งˆ์ผ ์Šคํ†ค ์ˆ˜์ • ์š”์ฒญํ•˜๋ฉด 200 ์ฝ”๋“œ๋ฅผ ์‘๋‹ตํ•œ๋‹ค")
@Test
void updateMilestone() throws Exception {
        // given
        long milestoneId = milestoneService.create(ORGANIZATION_TITLE, createMileStoneRequest);
        MilestoneRequest changedMilestoneRequest = new MilestoneRequest(TEST_TITLE, TEST_DESCRIPTION,
                TEST_DUE_DATE);
        // when
        mockMvc.perform(patch("/api/" + ORGANIZATION_TITLE + "/milestones/" + milestoneId)
                        .content(objectMapper.writeValueAsString(changedMilestoneRequest))
                        .contentType(MediaType.APPLICATION_JSON)
                        .accept(MediaType.APPLICATION_JSON)
                )
                // then
                .andDo(print())
                .andExpect(status().isOk());
}

๋งŒ์•ฝ์—์„œ milestoneService์˜ create์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ๋ณ€๊ฒฝ์„ ํ•˜๋ฉด ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋„ ๋Œ€์‘ํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

  • MockMvc ๋Œ€์‹  RestAssured์™€ Cucumber๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ BDD ๋ฐฉ์‹์œผ๋กœ ๊ฐœ์„ ํ•˜๋ ค๊ณ  ๊ฒ€ํ† ํ–ˆ์Šต๋‹ˆ๋‹ค.

RestAssured์™€ Cucumber์˜ ๋น„๊ต

RestAssured์˜ ์žฅ์ 

  • ์‹ค์ œ HTTP ํ…Œ์ŠคํŠธ: RestAssured๋Š” ์‹ค์ œ HTTP ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ํ…Œ์ŠคํŠธํ•˜์—ฌ ์‹ค์ œ ํ™˜๊ฒฝ์— ๋” ๊ฐ€๊นŒ์šด ํ…Œ์ŠคํŠธ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฐ„๊ฒฐํ•˜๊ณ  ๋ช…ํ™•ํ•œ API: API ํ…Œ์ŠคํŠธ์— ์ตœ์ ํ™”๋œ ๊ตฌ๋ฌธ์„ ์ œ๊ณตํ•˜์—ฌ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€ ๊ด€๋ฆฌ๋ฅผ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

  • API ํ…Œ์ŠคํŠธ์— ํŠนํ™”: ๋ณต์žกํ•œ API ์š”์ฒญ ๋ฐ ๋ฐ์ดํ„ฐ ํฌ๋งท์„ ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด API ํ…Œ์ŠคํŠธ์— ๋งค์šฐ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

given().
        config(RestAssured.config().xmlConfig(xmlConfig().declareNamespace("test", "http://localhost/"))).
when().
         get("/namespace-example").
then().
         body("foo.bar.text()", equalTo("sudo make me a sandwich!")).
         body(":foo.:bar.text()", equalTo("sudo ")).
         body("foo.test:bar.text()", equalTo("make me a sandwich!"));

Cucumber์˜ ์žฅ์ 

  • BDD ์ ‘๊ทผ๋ฒ•: Cucumber๋Š” ์ž์—ฐ ์–ธ์–ด๋กœ ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ž‘์„ฑํ•˜์—ฌ, ๋น„๊ธฐ์ˆ ์  ์ดํ•ด๊ด€๊ณ„์ž๋„ ํ…Œ์ŠคํŠธ ๊ณผ์ •์„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์ฐธ์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํŒ€ ๋‚ด ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜ ๊ฐ•ํ™”: BDD ์ ‘๊ทผ๋ฒ•์€ ๊ฐœ๋ฐœ์ž, ํ…Œ์Šคํ„ฐ, ๋น„์ฆˆ๋‹ˆ์Šค ์ดํ•ด๊ด€๊ณ„์ž ๊ฐ„์˜ ๋ช…ํ™•ํ•œ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์„ ์ด‰์ง„ํ•ฉ๋‹ˆ๋‹ค.

  • ์‚ฌ์šฉ์ž ์ค‘์‹ฌ์˜ ํ…Œ์ŠคํŠธ: ์‚ฌ์šฉ์ž์˜ ๊ฒฝํ—˜๊ณผ ์š”๊ตฌ์‚ฌํ•ญ์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์„ค๊ณ„ํ•˜๊ณ  ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Scenario: Breaker guesses a word
  Given the Maker has chosen a word
  When the Breaker makes a guess
  Then the Maker is asked to score

๋‚ด๊ฐ€ ์„ ํƒํ•œ ๋ฐฉ๋ฒ•๊ณผ ์ด์œ 

  • RestAssured๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์ œ HTTP ํ…Œ์ŠคํŠธ๋ฅผ ํ…Œ์ŠคํŠธ ํ• ์ˆ˜ ์žˆ๊ณ  ๊ฐ„๊ฒฐํ•˜๊ณ  ๋ช…ํ™•ํ•œ API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ€๋…์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๊ณ  ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์œ ์ง€ ๋ณด์ˆ˜๊ฐ€ ์‰ฝ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์—ฌ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ

  • ํ…Œ์ŠคํŠธ Step๋ฅผ ํ•œ๊ธ€ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ฉํ•˜๊ณ  ํ…Œ์ŠคํŠธ์˜ ๊ฐ€๋…์„ฑ๋ฅด ํ–ฅ์ƒ๋˜์˜€๊ณ  ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง์˜ ๋ณ€๊ฒฝ ๋”ฐ๋ผ ๋ณ€๊ฒฝ์ด ์ ์–ด์กŒ์Šต๋‹ˆ๋‹ค.

@DisplayName("๋‚ด ๊ด€์‹ฌ์ƒํ’ˆ์— ๋‹ด์€ ํ›„, ํ•ด๋‹น ๊ด€์‹ฌ์ƒํ’ˆ ์‚ญ์ œ")
@Test
void shouldRemoveProductToInterestedProductsList() {
    ์ถœ๋ ฅ_ํ•„๋“œ_์ถ”๊ฐ€("member_removeLikeProduct", spec);

    // given
    var id = ์ƒํ’ˆ์„_๋“ฑ๋กํ•œ๋‹ค(ayaanAccessToken, 1).jsonPath().getString("id");
    ๊ด€์‹ฌ์ƒํ’ˆ์—_๋‹ด๋Š”๋‹ค(id, albertAccessToken);

    // when
    var response = ๊ด€์‹ฌ์ƒํ’ˆ์—_์ œ๊ฑฐํ•œ๋‹ค(id, albertAccessToken, spec);

    // then
    ๊ด€์‹ฌ์ƒํ’ˆ์€_๋‹ด์€_์‘๋‹ต_๊ฒ€์ฆ(response);
}

Last updated

Was this helpful?