DevKim

[Test Code] ๋‹จ์œ„ ํ…Œ์ŠคํŠธ - Mockito & @MockMvcTest ๋ณธ๋ฌธ

Spring Boot

[Test Code] ๋‹จ์œ„ ํ…Œ์ŠคํŠธ - Mockito & @MockMvcTest

on_doing 2021. 7. 14. 22:47
728x90

๐Ÿƒ Mock์„ ์ด์šฉํ•œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ๐Ÿƒ


โœ”  ๋‹จ์œ„ ํ…Œ์ŠคํŠธ VS. ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ

- ๋‹จ์œ„ ํ…Œ์ŠคํŠธ (Unit Test)

์žฅ์ : ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ์ด๋‚˜ ํด๋ž˜์Šค์— ๋Œ€ํ•ด ์„ธ๋ฐ€ํ•œ ๋ถ€๋ถ„๊นŒ์ง€ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ 

๋‹จ์ : ๋ชจ๋“ˆ ๊ฐ„์— ์ƒํ˜ธ ์ž‘์šฉ ๊ฒ€์ฆ ๋ชปํ•จ

 

- ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ (Integration Test)

์žฅ์ : ๋‘ ๊ฐœ ์ด์ƒ์˜ ๋ชจ๋“ˆ์ด ์—ฐ๊ฒฐ๋œ ์ƒํƒœ๋ฅผ ํ…Œ์ŠคํŠธ ๋ชจ๋“ˆ ๊ฐ„์˜ ์—ฐ๊ฒฐ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ ๊ฒ€์ฆ ๊ฐ€๋Šฅ

๋‹จ์ : ๋„ˆ๋ฌด ๋ฌด๊ฑฐ์›€


์ง€๊ธˆ๊นŒ์ง„, ํ•ญ์ƒ @SpringBootTest๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋งŒ์„ ์ง„ํ–‰ํ–ˆ์—ˆ๋‹ค.

์‚ฌ์‹ค ์ง€๊ธˆ๊นŒ์ง€ ํฐ ํ”„๋กœ์ ํŠธ๋Š” ์ง„ํ–‰ํ•œ์ ์ด ์—†๊ธฐ์—, ๋ฌด๊ฒ๋‹ค๋Š” ๋Š๋‚Œ์€ ๋งŽ์ด ๋ชป ๋ฐ›์•˜๋Š”๋ฐ

์‹ค๋ฌด์—์„  ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ๋น ๋ฅด๊ฒŒ ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉด์„œ๋„ ๊ฐ€์žฅ ํšจ๊ณผ์ ์ด์–ด์„œ

์ž์ฃผ ์“ฐ์ด๋Š” ๊ฒƒ ๊ฐ™์œผ๋‹ˆ ๋ฏธ๋ฆฌ ์—ฐ์Šตํ•ด๋‘๋ ค๊ณ ํ•œ๋‹ค.

 

์‹ค์Šต์€ ๊ฐ„๋‹จํ•œ CRUD ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค๊ณ ,

์ด๊ฒƒ์ €๊ฒƒ ์ฐพ์•„๋ณด๋ฉด์„œ ์ด์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์•˜๋‹ค.

 

๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” Mockito์™€ @MockMvcTest๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•™์Šตํ•˜์˜€๋‹ค.


๐Ÿ“Œ Mock ๊ฐ์ฒด๋ž€?

  • ์‹ค์ œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๊ธฐ์— ์‹œ๊ฐ„, ๋น„์šฉ ๋“ฑ์˜ Cost๊ฐ€ ๋†’์€๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•œ๋‹ค. 
  • ๊ฐ€์งœ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ๊ฐ€์งœ๊ฐ์ฒด๊ฐ€ ์›ํ•˜๋Š”ํ–‰์œ„๋ฅผ ํ–ˆ๋Š”์ง€๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

๐Ÿ“Œ Controller Test ์ฝ”๋“œ ์ž‘์„ฑ๋ฒ•

  • MockMvc๋ฅผ ํ†ตํ•ด api๋ฅผ ํ˜ธ์ถœํ•˜๋ฉฐ ํ•ด๋‹น์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์˜์กดํ•˜๊ณ  ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ Mock๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด ์ฃผ์ž…ํ•ด์ค€๋‹ค.(@MockBean ์–ด๋…ธํ…Œ์ด์…˜ ์‚ฌ์šฉ)
  • Mock ๊ฐ์ฒด๋Š” ๊ฐ€์งœ๊ฐ์ฒด์ด๋ฏ€๋กœ ๋ฆฌํ„ด๋˜๋Š”๊ฐ’์ด ์—†์œผ๋ฏ€๋กœ, given & when ์„ ์‚ฌ์šฉํ•˜์—ฌ ์›ํ•˜๋Š” ๊ฐ’์„ ๋ฆฌํ„ด ํ•˜๋„๋ก ๋ฏธ๋ฆฌ ์ •์˜ํ•ด์ค€๋‹ค.
  • ๋กœ์ง์ด ์ง„ํ–‰๋œํ›„ ํ•ด๋‹น ํ–‰์œ„๊ฐ€ ์ง„ํ–‰๋๋Š”์ง€ verify๋ฅผ ํ†ตํ•ด ๊ฒ€์ฆํ•ด์ค๋‹ˆ๋‹ค.

๐Ÿ“Œ POST Method Test - ๊ธ€ ๋“ฑ๋ก ํ…Œ์ŠคํŠธ

@MockBean(JpaMetamodelMappingContext.class)
@WebMvcTest(HoneyPostApiController.class)
class HoneyPostApiControllerTest {

    @Autowired
    MockMvc mockMvc;

    @MockBean
    HoneyService honeyService;
    
    @DisplayName("๊ธ€ ๋“ฑ๋ก ํ…Œ์ŠคํŠธ")
    @Test
    public void createPost() throws Exception {
        //given
        HoneyPostApiDto honeyPostDto = HoneyPostApiDto.builder()
                .title("this is title")
                .author("juliekim")
                .content("this is content")
                .build();

        //when
        //then
        mockMvc.perform(post("/api/honey")
                .contentType(MediaType.APPLICATION_JSON)
                .content(new ObjectMapper().writeValueAsString(honeyPostDto)))
                .andExpect(status().isOk())
                .andDo(MockMvcResultHandlers.print());

    }

1. ์ „๋‹ฌํ•  DTO ์ƒ์„ฑ

2. post ๋ฐฉ์‹์œผ๋กœ ํ•ด๋‹น url์— ์ „๋‹ฌ

3. JSON ํƒ€์ž…์ž„์„ ๋ช…์‹œ

.contentType(MediaType.APPLICATION_JSON)

4. Body ์˜์—ญ์€ ๋ฌธ์ž์—ด๋กœ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ObjectMapper์„ ํ†ตํ•ด ๋ฌธ์ž์—ด JSON์œผ๋กœ ๋ณ€ํ™˜

.content(new ObjectMapper().writeValueAsString(honeyPostDto)))

5. ์‘๋‹ต ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ

.andDo(MockMvcResultHandlers.print())

print๋ฅผ ํ•˜๋ฉด ์ข€ ๋” ์ง๊ด€์ ์œผ๋กœ ํ™•์ธ๊ฐ€๋Šฅํ•˜๋‹ค.


๐Ÿ“Œ Get Method Test - ๋‹จ๊ฑด ์กฐํšŒ

    @DisplayName("๊ธ€ ์ƒ์„ธ ์กฐํšŒ ํ…Œ์ŠคํŠธ")
    @Test
    public void findOne() throws Exception{
        //given
        HoneyPost honeyPost = HoneyPost.builder()
                .title("this is title")
                .author("juliekim")
                .content("this is content")
                .build();

        //when
        when(honeyService.findOne(anyLong())).thenReturn(honeyPost);

        //then
        mockMvc.perform(get("/api/honey/{id}",1L))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.title").value(honeyPost.getTitle()))
                .andExpect(jsonPath("$.author").value(honeyPost.getAuthor()))
                .andExpect(jsonPath("$.content").value(honeyPost.getContent()))
                .andDo(MockMvcResultHandlers.print());

    }

(1) ์ €์žฅ ๋  ๊ฒƒ์ด๋ผ๊ณ  ๊ฐ€์ •ํ•  ๊ฐ์ฒด ์ƒ์„ฑ

(2) when : Service์˜ findOne ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰๋์„ ๋•Œ -> then : (1)์—์„œ ์ €์žฅํ•œ ๊ฐ์ฒด ๋ฐ˜ํ™˜

(3). GET์œผ๋กœ ๊ฐ€์ ธ์™”์„ ๋•Œ, ์˜ˆ์ƒํ•œ ๊ฐ’์ด ๋‚˜์˜ค๋Š”์ง€ ๊ฒ€์ฆ.


๐Ÿ“Œ GET Method Test - ๋‹ค์ค‘ ์กฐํšŒ

    @Test
    @DisplayName("๊ธ€ ๋ชฉ๋ก ์กฐํšŒ ํ…Œ์ŠคํŠธ")
    public void findPost() throws Exception {
        //given
        HoneyPostListResponseDto honeyPost = HoneyPostListResponseDto.builder()
                .title("this is title")
                .author("juliekim")
                .content("this is content")
                .build();

        HoneyPostListResponseDto honeyPost2 = HoneyPostListResponseDto.builder()
                .title("this is title2")
                .author("juliekim2")
                .content("this is content2")
                .build();


        List<HoneyPostListResponseDto> PostLists = new ArrayList<>();
        PostLists.add(honeyPost);
        PostLists.add(honeyPost2);

        //when
        when(honeyService.findAll()).thenReturn(PostLists);

        //then
        mockMvc.perform(get("/api/honey"))
                .andExpect(status().isOk())
                .andDo(MockMvcResultHandlers.print())
                .andExpect(jsonPath("$.[0].title").value(honeyPost.getTitle()))
                .andExpect(jsonPath("$.[0].author").value(honeyPost.getAuthor()))
                .andExpect(jsonPath("$.[0].content").value(honeyPost.getContent()))
                .andExpect(jsonPath("$.[1].title").value(honeyPost2.getTitle()))
                .andExpect(jsonPath("$.[1].author").value(honeyPost2.getAuthor()))
                .andExpect(jsonPath("$.[1].content").value(honeyPost2.getContent()))
                .andDo(MockMvcResultHandlers.print());
    }

(1) ์กฐํšŒ์‹œ ์กฐํšŒ์šฉ DTO๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, ์กฐํšŒ์šฉ DTO๋กœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ

(2) ์ž„์˜๋กœ ์ƒ์„ฑํ•œ ๋‘๊ฐœ์˜ DTO๋ฅผ List๋กœ ์ƒ์„ฑ

(3) service์˜ finAll ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ์„ฑํ•  ์‹œ, ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•ด ๋‘” List๊ฐ€ ๋‚˜์™€์•ผํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.

(4) Get์œผ๋กœ ๋ฐ›์•„์˜จ ๊ฐ์ฒด์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ๊ฒ€์ฆ

 

๋‘๊ฐœ๋ฅผ ์ž˜ ๊ฐ€์ ธ์™”๋‹ค โœ”


๐Ÿ“Œ PUT Method Test - ๊ธ€ ์ˆ˜์ • ํ…Œ์ŠคํŠธ

    @Test
    @DisplayName("๊ธ€ ์ˆ˜์ • ํ…Œ์ŠคํŠธ")
    public void test() throws Exception {

        //given
        String updateTitle = "updateTitle";
        String updateContent = "updateContent";

        HoneyPostUpdateDto requestDto = HoneyPostUpdateDto.builder()
                .title(updateTitle)
                .content(updateContent)
                .build();

        //when
        //then
        mockMvc.perform(put("/api/honey/{id}", 1L)
                .contentType(MediaType.APPLICATION_JSON)
                .content(new ObjectMapper().writeValueAsString(requestDto)))
                .andExpect(status().isOk())
                .andDo(MockMvcResultHandlers.print());

    }

 

get,put,delete,post

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;

 

 

728x90
Comments