[2] Spring Boot에서 테스트 코드 작성하기

도서, 스프링 부트와 AWS로 혼자 구협하는 웹 서비스(2019)를 토대로 공부한 내용입니다.

 

 

1. 테스트 코드 관련 개념

1.1. TDD란

  • TDD: 테스트가 주도하는 개발
  • 즉, 테스트 코드를 먼저 작성하는 것부터 시작

1.1.1. TDD-레드 그린 사이클

  • 실패하는 테스트를 먼저 작성한다 (RED)
  • 테스트가 통과하는 프로덕션 코드를 작성한다 (GREEN)
  • 테스트 통과시 프로덕션 코드를 리팩토링한다 (Refactor)

1.2. 단위 테스트란

  • TDD의 첫 단계인 기능단위 테스트 코드 작성
  • 테스트 코드를 굳이 먼저 작성하지 않아도 된다
  • 리팩토링이 포함되지 않는다
  • 테스트 코드만 작성하는 것을 이야기한다

1.2.1. 테스트 코드 작성 이유

  • 단위 테스트는 개발단계 초기 문제를 발견하게 도움
  • 단위 테스트는 개발자가 나중중에 코드를 리팩토링하거나 라이브러리 업그레이드 등에서 기존 기능이 올바르게 작동하는지 확인 가능(ex. 회귀 테스트)
  • 단위 테스트는 기능에 대한 불확실성을 감소시킴
  • 단위테스트는 시스템에 대한 실제 문서를 제공( 단위 테스트 자체가 문서로 사용)

이런 테스트 코드를 쓰면, system.out.println() 출력으로 눈으로 검증해야하는 불필요한 수동작업을 버릴 수 있다. 다시 정리하면 이렇게 정리된다

1. 빠른 피드백 가능 
2. 출력문과 같은 수동검증이 필요없다
3. 개발자가 만든 기능을 안전하게 보호한다

3의 경우는 테스트 코드가 기존 기능이 잘 작동됨을 보장해주기 대문에 다른 코드의 추가시의 문제를 조기에 찾을 수 있다.

1.3. 테스트프레임워크

xUnit-JUnit를 써보자.


 

2. Hello Controller 테스트 코드 작성하기

2.1. 폴더, 패키지, 클래스 생성

  • Java > (우클릭)Next → package 생성
  • 일반적으로 패키지명은 웹 사이트 주소의 역순 ex) practice.kyu.com → com.kyu.practice
  • Java > (우클릭)Next → class 생성
  • 이름은 임의로 Application으로 진행

여기까지 했으면 디렉토리가 이렇게 생성된다

2.2. Application 클래스 생성 & 테스트코드 작성

package com.kyu.practice.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.admin.SpringBootApplication;

@SpringBootApplication // 스프링 부트의 자동 설정, 스프링 Bean 읽기와 생성을 모두 자동 설정, 항상 프로젝트 최상단에 위치할 것.
public class Application {  //앞으로 진행될 프로젝트의 메인 클래스
    public static void main(String [] args){
        SpringApplication.run(Appllication.class, args); //내장 was(Web Application Server)실행
    }
}

2.2.1. Application 클래스가 하는 일

  • 앞으로 만들 프로젝트의 메인 클래스

2.2.2. @springBootApplication

  • 이 위치부터 설정을 읽어가므로 항상 프로제트 최사단 위치에 있어야 함

2.2.3. 내장 WAS

  • 별도의 외부 WAS없이 애플리케이션 시행시 내부 WAS를 실행함
  • 항상 서버에 톰캣을 설치할 필요가 없어진다
  • 스프링 부트로 만들어진 Jar파일을 실행하면 된다
  • 이를 통해 언제 어디서나 같은 환경의 스프링 부트를 배포할 수 있게 된다
  • 많은 회사에서 내장 WAS를 사용/권장 한다

2.3. Web패키지, HelloController생성

2.3.1. Web패키지 역할

  • 앞으로 컨트롤러와 관련된 클래스를 담을 패키지

2.3.2. HelloController로 간단한 API작성하기

package web;

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

@RestController // Json을 반환하는 컨트롤러로 만들어줌
public class HelloController {

    @GetMapping("/hello") // HTTP method > Get 요청을 받을 수 있는 API를 만듦
    public String hello(){
        return "hello";
    }
}

2.3.3. 테스트 코드를 작성할 클래스 생성

import com.sun.xml.internal.ws.developer.UsesJAXBContext;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMveTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMve;
import org.springframework.test.web.servlet.ResultActions;
import static org.springframework.test.web.servlet.request.MockMveRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMveResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMveResultMatchers.status;

@RunWith(SpringRunner.class) // 테스트 진행시 jUnit에 내장된 실행자 외의 다른 실행자를 실행시킴
@webMvcTest // 여러 스프링 테스트 어노테이션 중, Web에 집중할 수 있는 어노테이션
public class HelloControllerTest {
    @Autowired
    private MockMvc mvc;

    @Test
    public void hello가_리턴된다() throws Exception {
        String hello = "hello";

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

교재와 다른 점

  • jupiter5를 사용하기 위해서 책속 교재의 관련 패키지 임폴트문과 어노테이션, 클래스 호출문을 바꿨음.
  • 주석 참고

2.3.4. 테스트 코드 실행

  • RUN

  • 정상실행 확인

'