Spring MVC 테스팅

김병수·2022년 11월 17일
0
post-thumbnail

단위 테스트

메서드 단위로 진행하는 테스트. 단위 테스트를 하는 이유는 매번 HTTP 요청을 보내는 것은 비효율적이기 때문이다.

Given-When-Then 패턴

테스트의 가독성을 높이기 위한 패턴

  • Given
    테스트를 위한 준비과정. 필요한 전제 조건과 테스트 대상에 전달되는 입력 값
  • When
    테스트 할 동작을 지정
  • Then
    테스트의 결과를 검증. Assertioins 사용

JUnit

자바 애플리케이션을 테스트 하기 위한 테스트 프레임워크이다.

JUnit 기본 구조

 	@Test
    public void calculateStampCountTest() {
        // given
        int nowCount = 5;
        int earned = 3;
        int expected = 8;

        // when
        int actual = StampCalculator.calculateStampCount(nowCount, earned);

        // then
        Assertions.assertEquals(expected, actual);
    }

메서드에 @Test 애너테이션을 사용하고 Given-When-Then 패턴으로 테스트 케이스를 구성한다.

Assertion 메서드

  1. assertEquals() : 기댓값과 실제 값이 같은지 테스트
  2. assertNotNull() : 테스트 대상 객체가 null이 아닌지 테스트
  3. assertThrows() : 메서드 호출 시, NullPointerException이 발생하는지 테스트

테스트 케이스 실행 전, 전처리

  1. @BeforeEach : 테스트 케이스가 실행 직전에 먼저 실행되어 초기화 작업을 진행
  2. @BeforeAll : 테스트 케이스를 한꺼번에 실행 시키면 딱 한 번만 초기화 작업(BeforeEach와 다름)

슬라이스 테스트

하나의 계층에 구현한 기능들이 잘 동작하는지 특정 계층만 잘라서 하는 테스트.

API 계층 테스트

import com.codestates.member.dto.MemberDto;
import com.google.gson.Gson;
import org.junit.jupiter.api.Test;
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.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class MemberControllerTest2 {
    @Autowired
    private MockMvc mockMvc; //테스트에 필요한 가짜 객체

    @Autowired
    private Gson gson; //JSON 변환 라이브러리

    @Test
    void postMemberTest() throws Exception {
        // given
        MemberDto.Post post = new MemberDto.Post("hgd@gmail.com",
                                                        "홍길동",
                                                    "010-1234-5678");
        String content = gson.toJson(post);

        // when
        ResultActions actions =
                mockMvc.perform(
                                    post("/v11/members")
                                        .accept(MediaType.APPLICATION_JSON) // 응답 데이터 JSON 타입 설정
                                        .contentType(MediaType.APPLICATION_JSON)
                                        .content(content) // request body 데이터 설정
                                );

        // then
        MvcResult result = actions
                                .andExpect(status().isCreated()) // 201(OK)이 맞는지 검증
                                .andExpect(jsonPath("$.data.email").value(post.getEmail())) //JSON 형식 응답과 request body 데이터가 일치하는지 검증
                                .andExpect(jsonPath("$.data.name").value(post.getName()))   
                                .andExpect(jsonPath("$.data.phone").value(post.getPhone())) 
                                .andReturn();

        System.out.println(result.getResponse().getContentAsString());
    }
}

@SpringBootTest 애너테이션은 애플리케이션 테스트를 위한 애플리케이션 Context를 생성한다. @AutoConfigureMockMvc 애너테이션은 애플리케이션의 자동 구성 작업을 한다.

데이터 엑세스 계층 테스트

import com.codestates.member.entity.Member;
import com.codestates.member.repository.MemberRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest   
public class MemberRepositoryTest {
    @Autowired
    private MemberRepository memberRepository; 

    @Test
    public void saveMemberTest() {
        // given  
        Member member = new Member();
        member.setEmail("hgd@gmail.com");
        member.setName("홍길동");
        member.setPhone("010-1111-2222");

        // when  
        Member savedMember = memberRepository.save(member);

        // then  
        assertNotNull(savedMember); 
        assertTrue(member.getEmail().equals(savedMember.getEmail()));
        assertTrue(member.getName().equals(savedMember.getName()));
        assertTrue(member.getPhone().equals(savedMember.getPhone()));
    }
}

@DataJpaTest 애너테이션은 MemberRepository의 기능을 정상적으로 사용하기 위한 Configuration을 Spring이 자동으로 해준다. 이 애너테이션은 @Transactional을 포함하기 때문에 하나의 테스트 케이스 실행이 종료되고 DB에 저장된 데이터는 rollback 처리 된다. 이는 데이터베이스가 초기 상태로 계속 유지된다는 의미이다.

profile
BE 개발자를 꿈꾸는 대학생

0개의 댓글