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개의 댓글

관련 채용 정보