관리 메뉴

JIE0025

[Testcode][통합] CategoryIntegrationTest 본문

백엔드/테스트

[Testcode][통합] CategoryIntegrationTest

Kangjieun11 2023. 1. 9. 02:31
728x90

 

통합테스트를 진행하기 위해서는 몇가지 고려할 점이 있다. 

  1. 데이터베이스 서버를 작동시켜야한다.
  2. 테스트가 끝나고 데이터가 지워지지 않기 때문에 다음 테스트시에 해당 데이터를 어떻게 처리할지
    • 데이터베이스 초기화를 진행할지
    • 해당 데이터로 다음 테스트를 진행할지
      • 테스트 순서는 어떻게 정해줄건지 등등
  3. 어디까지 검증할것인가?

 

package com.FlagHome.backend.domain.category.integration;

import com.FlagHome.backend.domain.category.controller.CategoryController;
import com.FlagHome.backend.domain.category.dto.CategoryPostDto;
import com.FlagHome.backend.domain.category.entity.Category;
import com.FlagHome.backend.domain.category.mapper.CategoryMapper;
import com.FlagHome.backend.domain.category.repository.CategoryRepository;
import com.FlagHome.backend.domain.category.service.CategoryService;
import com.FlagHome.backend.global.exception.CustomException;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.web.context.WebApplicationContext;

import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;



@SpringBootTest
@AutoConfigureMockMvc
@WebAppConfiguration
@TestMethodOrder(value = MethodOrderer.DisplayName.class)
//@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class CategoryIntegrationTest {
    private final String DEFAULT_URL = "/api/categories";

    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private CategoryRepository categoryRepository;


    @Test
    @DisplayName("[통합1] depth가 0인 카테고리 추가 테스트")
    public void createCategoryDepth0Test() throws Exception {

        //given : 데이터를 생성한다 (어떤기능을 테스트하기 위한 파라미터나 미리 생성하는 데이터
        CategoryPostDto categoryPostDto = CategoryPostDto.builder()
                .koreanName("활동").englishName("activity").categoryDepth(0L).build();

        //when//then : 테스트 진행 메서드 호출 :: 데이터베이스에 알고리즘이라는 이름을 가진 카테고리가 생성이 됨
        mockMvc.perform(
                        post(DEFAULT_URL)
                                .contentType(MediaType.APPLICATION_JSON)
                                .content(objectMapper.writeValueAsString(categoryPostDto))
                                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isCreated())
                .andExpect(header().string("location", is(startsWith(DEFAULT_URL))));

        //findAll시 depth가 0인 카테고리를 가져오기 때문에 전체리스트 사이즈 체크
        List<Category> allList = categoryRepository.findAll();
        assertThat(allList.size(),is(equalTo(1)));

    }

    @Test
    @DisplayName("[통합2] depth가 1인 카테고리 추가 테스트")
    public void createCategoryDepth1Test() throws Exception {

        //given
        //부모로 1L인 데이터 설정 (post에서 테스트한 데이터)
        Long parentId = 1L;
        Category parent = categoryRepository.findById(parentId).orElse(null);


        Long categoryId = 2L;
        CategoryPostDto categoryPostDto = CategoryPostDto.builder()
                .koreanName("스터디").englishName("study").categoryDepth(1L).parentId(parentId).build();

        //when
        ResultActions result = mockMvc.perform(
                post(DEFAULT_URL)
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(categoryPostDto))
                        .accept(MediaType.APPLICATION_JSON));

        //then
        Category findCreatedCategory = categoryRepository.findById(categoryId).orElse(null);

        assertThat(findCreatedCategory.getParent().getId(), is(equalTo(parent.getId())));
        assertThat(findCreatedCategory.getKoreanName(), is(equalTo(categoryPostDto.getKoreanName())));
        assertThat(findCreatedCategory.getEnglishName(), is(equalTo(categoryPostDto.getEnglishName())));
        assertThat(findCreatedCategory.getCategoryDepth(), is(equalTo(categoryPostDto.getCategoryDepth())));


        result.andExpect(status().isCreated())
                .andExpect(header().string("location", is(startsWith(DEFAULT_URL))));

    }

    @Test
    @DisplayName("[통합3] 카테고리 수정 테스트")
    public void updateCategoryTest() throws Exception {

        //given
        //id가 2L인 카테고리 수정
        long categoryId = 2L;
        String updateKoreanName = "알고리즘-코테반";
        String updateEnglishName = "algorithm-codetest";

        CategoryPostDto update = CategoryPostDto.builder()
                .koreanName(updateKoreanName)
                .englishName(updateEnglishName).build();

        String content = objectMapper.writeValueAsString(update);

        //when

        ResultActions resultActions = mockMvc.perform(
                patch(DEFAULT_URL+"/{category-id}",categoryId)
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(content)
                        .accept(MediaType.APPLICATION_JSON)
        );

        //then
        resultActions.andExpect(status().isOk());

        Category updatedCategory = categoryRepository.findById(categoryId).orElse(null);
        assertThat(updatedCategory.getKoreanName(), is(equalTo(updateKoreanName)));
        assertThat(updatedCategory.getEnglishName(), is(equalTo(updateEnglishName)));
    }



    //추가랑 수정까지 클래스단위로 한번에 돌리면 문제가 생겨서 고민중임 데이터를 왜 못가져올까?
    //테스트케이스가 동시처리되나? 그럼말이 안되는게 수정이 잘 되면 안됨
    //결국 무슨 순서로 테스트가 되는지 확인이 필요함 (23.01.08 강지은)

    // 동작순서를 지정할 수 있는 어노테이션 발견!
    //@TestMethodOrder
    // MethodName, DisplayName, OrderAnnotation - @Order(n)

    @Test
    @DisplayName("[통합4] 전체 카테고리 가져오기 테스트")
    public void getAllCategiesTest() throws Exception {

        //given : 먼저 저장된 데이터를 given으로 줌

        //when
        ResultActions resultActions = mockMvc.perform(
                get(DEFAULT_URL).accept(MediaType.APPLICATION_JSON)
        );


        //then
        resultActions.andExpect(status().isOk());

        List<Category> allCategoryList = categoryRepository.findAll();
        //assertThat(allCategoryList.size(), is(equalTo(2))); >>

        Category id1depth0Category = allCategoryList.get(0);
        assert id1depth0Category.getCategoryDepth() == 0;
        //assert id1depth0Category.getChildren() == null;


        //assert id2depth1Category.getParent() == id1depth0Category;


    }
    @Test
    @DisplayName("[통합5] Board 삭제 테스트")
    public void deleteCategoryTest() throws Exception {

        //given
        Long deleteId = 2L;

        //when
        ResultActions resultActions =mockMvc.perform(
                delete(DEFAULT_URL+"/"+deleteId)
        );

        //then
        resultActions.andExpect(status().isNoContent());
        assertThrows(CustomException.class, () -> categoryService.deleteCategory(deleteId));
    }
}