[Springboot] 스프링 부트에서 테스트 코드 작성하기!

hi·2022년 8월 30일
0

spring boot

목록 보기
4/5

02 스프링 부트에서 테스트 코드를 작성하자

  • 단위 테스트
키워드내용
단위테스트기능 단위의 테스트 코드를 작성하는 것
장점- 개발단계 초기에 문제를 발견하게 도와준다.
- 나중에 리팩토링이나 라이브러리 업그레이드 등에서 기존 기능이 올바르게 작동하는지 확인할 수 있다 (예, 회귀 테스트)
- 기능에 대한 불확실성을 감소시킨다.
- 시스템에 대한 실제 문서를 제공한다. (단위 테스트 자체를 문서로 사용할 수 있음)

단위 테스트는 새로운 기능이 추가될 때, 기존 기능이 잘 작동되는 것을 보장해줌


  • 대표적 테스트 프레임워크
키워드내용
JUnitJAVA
DBUnitDB
CppUnitC++
NUnit.net

2.2 Hello Controller 테스트 코드 작성하기

  • Application (메인)클래스 추가
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
키워드내용
@SpringBootApplication- 스프링 부트 자동 설정, 스프링 Bean 읽기와 생성을 모두 자동으로 설정함
- 해당 어노테이션이 선언된 위치부터 설정을 읽어가기 때문에 프로젝트 최상단에서 선언할 것
SpringApplication.run내장 WAS 실행 (서버에 별도의 톰켓 설치 작업을 안해도 됨, 서버 실행 시 JAR Runnable File 만 클릭하면 실행할 수 있음)

  • 간단한 컨트롤러 구현
package org.example.jodu_01_Starter.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }

}

/hello 로 요청이 오면 문자열 hello 를 반환함

키워드내용
@RestController- 컨트롤러를 JSON 을 반환하는 컨트롤러로 만들어줌
- 예전에 @ResponseBody 를 각 메소드마다 선언했던 것을 한번에 사용할 수 있게 해줌
@GetMapping- HTTP Method 인 Get 의 요청을 받을 수 있는 API 를 만들어줌
- 예전에 @RequestMapping(method = RequestMethod.GET) 으로 사용되던 거

  • 테스트 코드 구현
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = HelloController.class)
public class HelloControllerTest {

    @Autowired
    private MockMvc mvc;

    @Test
    public void hello() throws Exception {

        String hello = "hello";

        mvc.perform(MockMvcRequestBuilders.get("/hello"))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.content().string(hello));
    }

}
키워드내용
@RunWith(SpringRunner.class)- 테스트를 진행할 때 JUnit에 내장된 실행자 외에 파라메타에 선언한 실행자를 실행
- SpringRunner 는 스프링 실행자를 사용
- 스프링부트 테스트와 JUnit 사이에 연결자 역할
@WebMvcTest- 여러 스프링 테스트 어노테이션 중, Web (Spring MVC)에 집중할 수 있는 어노테이션
- 선언할 경우 @Controller, @ControllerAdvice 등 사용 가능 (@Service, @Component, @Repository 등은 사용 불가)
@Autowired- 스프링이 관리하는 빈 (Bean)을 주입 받음
private MockMvc mvc- 웹 API 를 테스트할 때 사용
- 스프링 MVC 테스트의 시작점
- 이 클래스를 통해 HTTP GET, POST 등에 대한 API 테스트를 할 수 있다.
mvc.perform(MockMvcRequestBuilders.get("/hello"))- MockMvc 를 통해 /hello 주소로 HTTP GET 요청을 함
- 체이닝이 지원되어 여러 검증 기능을 이어서 선언 가능
.andExpect(MockMvcResultMatchers.status().isOk())- mvc.perform 의 결과를 검증
- HTTP Header 의 Status 를 검증
- 200, 404, 500 등의 상태 검증
- 여기선 OK (200) 인지 아닌지를 검중
.andExpect(MockMvcResultMatchers.content().string(hello))- mvc.perform 의 결과를 검증
- 응답 본문의 내용을 검증
- Controller 에서 "hello" 를 리턴하는 지 검증


2.3 롬복 소개

롬복이란? 개발 시 자주 사용하는 Getter, Setter, 기본생성자, toString 등을 어노테이션으로 자동 생성해줌

 implementation 'org.projectlombok:lombok:'

프로젝트마다 build.gradle 라이브러리 추가, Enable annotation processing 체크하기



2.4 Hello Controller 코드를 롬복으로 전환하기

  • HelloResponseDto 추가
package org.example.jodu_01_Starter.dto;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class HelloResponseDto {

    private final String name;

    private final int amount;
    
}
keyworddescription
@Getter- 선언된 모든 필드의 get 메소드를 생성해줌
@RequiredArgsConstructor- 선언된 모든 final 필드가 포함된 생성자를 생성해줌
- final 이 없는 필드는 생성자에 포함되지 않음

  • HelloResponseDto 테스트 코드 작성
package org.example.jodu_01_Starter.dto;

import org.junit.Test;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

public class HelloResponseDtoTest {

    @Test
    public void lombokFunctionTest() {

        /*given*/
        String name = "test";

        int amount = 1000;


        /*when*/
        HelloResponseDto dto = new HelloResponseDto(name, amount);


        /*then*/
        assertThat(dto.getName()).isEqualTo(name);
        assertThat(dto.getAmount()).isEqualTo(amount);

    }
}
keyworddescription
assertThat- assertj 라는 테스트 검증 라이이브러리의 검증 메소드임.
- 검증하고 싶은 대상을 매서드 인자로 받음
- 메소드 체이닝이 지원되어 isEqualTo 와 같이 메소드를 이어서 사용할 수 있다.
isEqualTo- assertj 의 동등 비교 메소드임.
- assertThat 에 있는 값과 isEqaulTo 의 값을 비교해서 같을 때만 성공!

JUnit 과 비교했을 때 assertj 의 장점

  • CoreMatchers 와 달리 추가적으로 라이브러리가 필요하지 않다.
    • Junit 의 assertThat 을 쓰게 되면 is() 와 같이 CoreMatchers 라이브러리가 필요하다.
  • 자동완성이 좀 더 확실하게 지원된다.
    • IDE 에서는 CoreMatchers 와 같은 Mather 라이브러리의 자동완성 지원이 약하다.
  • 실행결과


  • HelloController 에서 ResponseDTO 사용
    @GetMapping("/hello/dto")
    public HelloResponseDto HelloDto(@RequestParam("name") String name, @RequestParam("amount") int amount) {
        return new HelloResponseDto(name, amount);
    }
keyworddescription
@ReqeustParam- 외부에서 API 로 넘긴 파라미터를 가져오는 어노테이션임
- 여기서는 외부에서 name (@RequestParam("name")) 이란 이름으로 넘긴 파라미터를 메소드 파라미터 name(String name) 에 저장하게 됨.

  • HelloController API 테스트
package org.example.jodu_01_Starter.controller;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = HelloController.class)
public class HelloControllerTest {

    @Autowired
    private MockMvc mvc;

    @Test
    public void hello() throws Exception {

        String hello = "hello";

        mvc.perform(MockMvcRequestBuilders.get("/hello"))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.content().string(hello));
    }

    @Test
    public void HelloDto_return() throws Exception {

        String name = "hello";

        int amount = 1000;

        mvc.perform(MockMvcRequestBuilders.get("/hello/dto").param("name", name).param("amount", String.valueOf(amount)))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(jsonPath("$.name", is(name)))
                .andExpect(jsonPath("$.amount", is(amount)));


    }

}
keyworddescription
param- API 테스트할 때 사용될 요청 파라미터를 설정한다.
- 값은 String 만 허용됨
- 따라서 숫자/날짜 등의 데이터를 등록할 때는 문자열로 변경해야 함
jsonPath- JSON 응답값을 필드별로 검증할 수 있는 메서드이다.
- $ 을 기준으로 필드명을 명시한다.
- 여기서는 bane 과 amount 를 검증하니 $.name, $.amount 로 검증한다.
  • api 테스트 결과

0개의 댓글