IT๊ณต๋ถ€์ผ๊ธฐ
article thumbnail

๐Ÿ” Given-When-Then ํŒจํ„ด

public void getAllMembers() throws Exception {

    // given
    final String url = "/test";
    Member savedMember = memberRepository.save(new Member(1L, "ํ™๊ธธ๋™"));
    
    // when
    final ResultActions result = mockMvc.perform(get(url)	// 1
    	.accept(MediaType.APPLICATION_JSON));               	// 2
        
    // then
    result
    	.andExpect(status().isOk());				// 3
        
        // 4
        .andExpect(jsonPath("$[0].id").value(savedMember.getId()))
        .andExpect(jsonPath("$[0].name").value(savedMember.getName()));

}

Given : ๋ฉค๋ฒ„๋ฅผ ์ €์žฅ

When : ๋ฉค๋ฒ„ ๋ฆฌ์ŠคํŠธ๋ฅผ ์กฐํšŒํ•˜๋Š” API ํ˜ธ์ถœ

Then : ์‘๋‹ต ์ฝ”๋“œ๊ฐ€ 200 OK์ด๊ณ , ๋ฐ˜ํ™˜๋ฐ›์€ ๊ฐ’ ์ค‘์— 0๋ฒˆ์งธ ์š”์†Œ์˜ id์™€ name์ด ์ €์žฅ๋œ ๊ฐ’๊ณผ ๊ฐ™์€์ง€ ํ™•์ธ

 

1. perform() : ์š”์ฒญ์„ ์ „์†กํ•˜๋Š” ์—ญํ• ํ•˜๋Š” ๋ฉ”์„œ๋“œ

    ๊ฒฐ๊ณผ๋กœ resultActions ๊ฐ์ฒด๋ฅผ ๋ฐ›๊ณ  ๋ฐ˜ํ™˜๊ฐ’์„ ๊ฒ€์ฆ, ํ™•์ธํ•˜๋Š” andExpect()๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•ด์คŒ.

 

2. accept() : ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ ๋ฌด์Šจ ํƒ€์ž…์œผ๋กœ ์‘๋‹ต์„ ๋ฐ›์„์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ

 

3. andExpect() : ์‘๋‹ต์„ ๊ฒ€์ฆ

OK(200)์„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ์ด์— ํ•ด๋‹นํ•˜๋Š” ๋ฉ”์„œ๋“œ isOk๋ฅผ ์‚ฌ์šฉํ•ด ํ™•์ธํ•˜๊ธฐ

 

4. jsonPath("$[0].${ํ•„๋“œ๋ช…}") : JSON ์‘๋‹ต๊ฐ’์˜ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ์—ญํ• ํ•˜๋Š” ๋ฉ”์„œ๋“œ

0๋ฒˆ์งธ ๋ฐฐ์—ด์— ๋“ค์–ด์žˆ๋Š” ๊ฐ์ฒด์˜ id, name๊ฐ’ ๊ฐ€์ ธ์˜ค๊ณ  ์ €์žฅ๋œ ๊ฐ’๊ณผ ๊ฐ™์€์ง€ ํ™•์ธ

 

์ฝ”๋“œ ๋งคํ•‘ ๋ฉ”์„œ๋“œ ์„ค๋ช…
200 OK isOk() HTTP์‘๋‹ต ์ฝ”๋“œ๊ฐ€ 200 OK์ธ์ง€ ๊ฒ€์ฆ
201 Created isCreated() ... 201 Created์ธ์ง€ ๊ฒ€์ฆ
400 Bad Request isBadRequest() ... 400 Bad Request์ธ์ง€ ๊ฒ€์ฆ
403 Forbidden isForbidden() ... 403 Forbidden์ธ์ง€ ๊ฒ€์ฆ 
404 Not Found isNotFound() ... 404 Not Found์ธ์ง€ ๊ฒ€์ฆ
400๋ฒˆ๋Œ€ ์‘๋‹ต ์ฝ”๋“œ is4xxClientError() ...400๋ฒˆ๋Œ€ ์‘๋‹ต ์ฝ”๋“œ์ธ์ง€ ๊ฒ€์ฆ
500 Internal Server Error isinternalServerError() ... 500 Internal Server Error์ธ์ง€ ๊ฒ€์ฆ
500๋ฒˆ๋Œ€ ์‘๋‹ต ์ฝ”๋“œ is5xxServererror() ...500๋ฒˆ๋Œ€ ์‘๋‹ต ์ฝ”๋“œ์ธ์ง€ ๊ฒ€์ฆ

 

 

๐Ÿ” ์Šคํ”„๋ง ๋ถ€ํŠธ ์Šคํƒ€ํ„ฐ ํ…Œ์ŠคํŠธ ๋ชฉ๋ก

JUnit: ์ž๋ฐ” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์šฉ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ

     - ํ…Œ์ŠคํŠธ ๋ฐฉ์‹์„ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋Š” ์• ๋„ˆํ…Œ์ด์…˜์„ ์ œ๊ณต

     - @Test ์• ๋„ˆํ…Œ์ด์…˜์œผ๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑ, ๋…๋ฆฝ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ

     - ์˜ˆ์ƒ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ์–ด์„ค์…˜ ๋ฉ”์„œ๋“œ ์ œ๊ณต

     - ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์ด ๋‹จ์ˆœ, ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ ์‹œ๊ฐ„์ด ์ ์Œ

     - ์ž๋™ ์‹คํ–‰, ์ž์ฒด ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๊ณ  ์ฆ‰๊ฐ์ ์ธ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณต

     - @DisplayName : ํ…Œ์ŠคํŠธ ์ด๋ฆ„์„ ๋ช…์‹œํ•˜๋Š” ์• ๋„ˆํ…Œ์ด์…˜

     - assertEquals(๊ธฐ๋Œ€ํ•˜๋Š” ๊ฐ’, ์‹ค์ œ๋กœ ๊ฒ€์ฆํ•  ๊ฐ’) : ๊ฒ€์ฆ ๋ฉ”์„œ๋“œ

 

Spring Test & Spring Boot Test : ์Šคํ”„๋ง ๋ถ€ํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ์ง€์›

AssertJ : ๊ฒ€์ฆ๋ฌธ์ธ ์–ด์„ค์…˜์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

 

     - JUniot๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด ๊ฒ€์ฆ๋ฌธ์˜ ๊ฐ€๋…์„ฑ์„ ํ™• ๋†’์—ฌ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

     - Assertions.assertEquals(a + b, sum) -> assertThat(a + b).isEquals(sum) ๊ฐ€๋…์„ฑ ๋†’์ž„

     - ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ

๋ฉ”์„œ๋“œ ์ด๋ฆ„ ์„ค๋ช…
isEqualTo(A) A๊ฐ’๊ณผ ๊ฐ™์€์ง€ ๊ฒ€์ฆ
isNotEqualTo(A) A๊ฐ’๊ณผ ๋‹ค๋ฅธ์ง€ ๊ฒ€์ฆ
contains(A) A ๊ฐ’์„ ํฌํ•จํ•˜๋Š”์ง€ ๊ฒ€์ฆ
doesNotContain(A) A ๊ฐ’์„ ํฌํ•จํ•˜์ง€ ์•Š๋Š”์ง€ ๊ฒ€์ฆ
startsWith(A) ์ ‘๋‘์‚ฌ๊ฐ€ A์ธ์ง€ ๊ฒ€์ฆ
endsWith(A) ์ ‘๋ฏธ์‚ฌ๊ฐ€ A์ธ์ง€ ๊ฒ€์ฆ
isEmpty() ๋น„์–ด์žˆ๋Š” ๊ฐ’์ธ์ง€ ๊ฒ€์ฆ
isNotEmpty() ๋น„์–ด์žˆ์ง€ ์•Š์€ ๊ฐ’์ธ์ง€ ๊ฒ€์ฆ
isPositive() ์–‘์ˆ˜์ธ์ง€ ๊ฒ€์ฆ
isNegative() ์Œ์ˆ˜์ธ์ง€ ๊ฒ€์ฆ
isGreaterThan(1) 1๋ณด๋‹ค ํฐ ๊ฐ’์ธ์ง€ ๊ฒ€์ฆ
isLessThan(1) 1๋ณด๋‹ค ์ž‘์€ ๊ฐ’์ธ์ง€ ๊ฒ€์ฆ

 

 

Hamcrest : ํ‘œํ˜„์‹์„ ๋ณด๋‹ค ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” Matcher ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

Mockito : ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉํ•  ๊ฐ€์งœ ๊ฐ์ฒด์ธ ๋ชฉ ๊ฐ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค๊ณ , ๊ด€๋ฆฌํ•˜๊ณ , ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ง€์›ํ•˜๋Š” ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ

JSONassert : JSON์šฉ ์–ด์„ค์…˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

JsonPath : JSON ๋ฐ์ดํ„ฐ์—์„œ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ์„ ํƒํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

 

 

๐Ÿ” ์• ๋„ˆํ…Œ์ด์…˜์— ๋”ฐ๋ฅธ ์‹คํ–‰ ์ˆœ์„œ

1) @BeforeAll : ์ „์ฒด ํ…Œ์ŠคํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „ ์ฒ˜์Œ ํ•œ ๋ฒˆ ์‹คํ–‰

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์—ฐ๊ฒฐํ•ด์•ผ ํ•˜๊ฑฐ๋‚˜ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ์ดˆ๊ธฐํ™”ํ•  ๋•Œ์™€ ๊ฐ™์ด ์‚ฌ์šฉ๋จ

ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”์„œ๋“œ๋ฅผ static์œผ๋กœ ์„ ์–ธ

 

2) @BeforeEach : ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „ ๋งค๋ฒˆ ์‹คํ–‰

๊ฐ์ฒด๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ฑฐ๋‚˜ ํ…Œ์ŠคํŠธ์— ํ•„์š”ํ•œ ๊ฐ’์„ ๋ฏธ๋ฆฌ ๋„ฃ์„ ๋•Œ์™€ ๊ฐ™์ด ์‚ฌ์šฉ๋จ.

๊ฐ ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•ด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋ฏ€๋กœ static์œผ๋กœ ์„ ์–ธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

3) @AfterEach : ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ์ข…๋ฃŒํ•˜๊ธฐ ์ „ ๋งค๋ฒˆ ์‹คํ–‰

ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•ด์•ผ ํ•  ๋•Œ์™€ ๊ฐ™์ด ์‚ฌ์šฉ๋จ.

๊ฐ ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•ด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋ฏ€๋กœ static์œผ๋กœ ์„ ์–ธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

4) @AfterAll : ์ „์ฒด ํ…Œ์ŠคํŠธ ๋งˆ์นœ ํ›„ ์ข…๋ฃŒํ•˜๊ธฐ ์ „ ํ•œ ๋ฒˆ ์‹คํ–‰

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ์ข…๋ฃŒํ•˜๊ฑฐ๋‚˜ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ž์›์„ ํ•ด์ œํ•  ๋•Œ์™€ ๊ฐ™์ด ์‚ฌ์šฉ๋จ.

ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”์„œ๋“œ๋ฅผ static์œผ๋กœ ์„ ์–ธ

 

 

๐Ÿ”ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์• ๋„ˆํ…Œ์ด์…˜ ์ •๋ฆฌ

@DisplayName : ํ…Œ์ŠคํŠธ ์ด๋ฆ„ ๋ช…์‹œ

 

@Test : ์ด๋ฅผ ๋ถ™์ธ ๋ฉ”์„œ๋“œ๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

@SpringBootTest : ๋ฉ”์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํด๋ž˜์Šค์— ์ถ”๊ฐ€ํ•˜๋Š” ์• ๋„ˆํ…Œ์ด์…˜์ธ @SpringBootApplication์ด ์žˆ๋Š” ํด๋ž˜์Šค๋ฅด ์ฐพ๊ณ  ๊ทธ ํด๋ž˜์Šค์— ํฌํ•จ๋˜์–ด ์žˆ๋Š” ๋นˆ์„ ์ฐพ์€ ๋‹ค์Œ ํ…Œ์ŠคํŠธ์šฉ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๋ผ๋Š” ๊ฒƒ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

 

@AutoConfigureMockMvc : MockMvc๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ž๋™์œผ๋กœ ๊ตฌ์„ฑ

MockMvc : ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„œ๋ฒ„์— ๋ฐฐํฌํ•˜์ง€ ์•Š๊ณ ๋„ ํ…Œ์ŠคํŠธ์šฉ MVCํ™˜๊ฒฝ์„ ๋งŒ๋“ค์–ด ์š”์ฒญ ๋ฐ ์ „์†ก, ์‘๋‹ต ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค. ์ฆ‰, ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ…Œ์ŠคํŠธํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ํด๋ž˜์Šค.

 

@BeforeEach : ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „ ์‹คํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ์— ์ ์šฉ

 

@AfterEach : ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•œ ์ดํ›„์— ์‹คํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ์— ์ ์šฉ