테스트 코드 작성

박찬미·2021년 4월 11일
0

Spring Boot

목록 보기
5/17
  • TDD
    테스트가 주도하는 개발
    Red : 항상 실패하는 테스트 먼저 작성
    Green : 테스트가 통과하는 프로덕션 코드 작성
    Refactor : 테스트가 통과하면 프로덕션 코드 리팩토링
    추가 설명

  • 단위 테스트
    TDD의 첫 번째 단계인 기능 단위의 테스트 코드 작성(순수)

이번에 나는 단위 테스트 코드만 한다.

테스트 코드는 왜 작성해야 할까?

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


단위 테스트 이전과 이후

  1. 코드 작성
  2. 프로그램(Tomcat) 실행
  3. API 테스트 도구(Postman..)로 HTTP 요청
  4. 요청 결과 눈으로 검증
  5. 원치 않은 결과시 프로그램(Tomcat) 중지 후 코드 수정
  6. 반복

테스트 코드는 이런 번거로움을 해결할 수 있다.

  • 톰캣 실행, 중지 반복하지 않아도 된다.
  • 눈으로 검증이 아닌 코드가 자동으로 검증해준다.
  • 다른 코드에 영향을 주지 않고 보호해준다.


테스트 코드 작성

테스트 코드 작성을 도와주는 프레임워크로 xUnit이 가장 대중적이다.

  • JUnit - java
  • DBUnit - DB
  • CppUnit - C++
  • NUnit - .net

나는 자바용인 JUnit을 사용한다.(JUnit4)

1. 패키지 생성

Java 디렉토리에 패키지를 생성한다.

com.springboot.example.project1로 생성해주었다.

2. 패키지 안에 자바 클래스 생성

Application 이름으로 생성

package com.springboot.example.project1;

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

// 스프링 부트의 자동 설정, 스프링 Bean 읽기와 생성 모두 자동 설정
// 프로젝트는 @SpringBootApplication 위치부터 설정을 읽으므로 항상 프로젝트 최상단 위치
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        // 내장 WAS(톰캣 필요x) 실행 -> 언제 어디서나 같은 환경에서 스프링 부트 배포 가능
        // 스프링 부트로 만들어진 Jar 파일(실행 가능한 패키징 파일)로 실행
        SpringApplication.run(Application.class, args);
    }
}

3. 생성한 패키지 하위에 web 패키지 생성

앞으로 컨트롤러와 관련된 클래스들은 모두 이 패키지에 담게 된다.

4. web 패키지에 HelloController 클래스 생성

간단한 API 만들어보겠다.

package com.springboot.example.project1.web;

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

// JSON을 반환하는 컨트롤러로 만들어준다.(API)
// 과거 @ResponseBody를 각 메소드마다 선언하지 않고, 한 번에 사용하는 거라고 보면 된다.
@RestController
public class HelloController {
    // Get 요청시 매핑되는 곳
    // 과거 @RequestMapping(method = RequestMethod.GET)
    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }
}

5. 테스트 코드로 검증

먼저 main 패키지말고 test 패키지에서 위에 main에 만든 것처럼 패키지 그대로 만든다.(귀찮으니 사진 생략)

그리고 web 패키지 안에 컨트롤러 자바 클래스 생성(테스트 클래스는 뒤에 Test 붙인다.)

package com.springboot.example.project1.web;

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 static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

// 테스트를 진행할 때 JUnit에 내장된 실행자 외에 다른 실행자 실행(SpringRunner)
// 스프링 부트 테스트와 JUnit 사이의 연결자
@RunWith(SpringRunner.class)
// Web(Spring MVC)에 집중할 수 있는 스프링 테스트 어노테이션
// @Controller, @ControllerAdvice 등 사용 가능(@Service, @Component, @Repository 등 사용 불가)
@WebMvcTest(controllers = HelloController.class)
public class HelloControllerTest {
    // 빈 자동 주입(IoC)
    @Autowired
    private MockMvc mvc; // 웹 API 테스트시 사용(HTTP GET/POST 등 API 테스트 가능), 스프링 MVC 테스트 시작점

    @Test
    public void hello() throws Exception{
        String hello = "hello";
        
        // MockMvc를 통해 /hello 주소로 HTTP GET 요청
        // 여러 검증 기능 선언 가능
        mvc.perform(get("/hello"))
                // 결과 검증(상태 검증 = 200, 404, 500 등)
                // isOk는 200
                .andExpect(status().isOk())
                // 결과 검증(응답 내용 검증 = hello로 리턴되는지)
                .andExpect(content().string(hello));
    }
}

테스트 코드를 작성했다.

화살표를 눌러 실행해본다.

여기서 오류가 났다. index.html 보라면서 task:test가 execution 오류가 떴다.
뭔지 몰라서 프로젝트 갈아엎고 하다가 그레이들 버전 문제인가? 했다.
근데 깃에 커밋과 푸시를 하고 테스트 실행하니까 된다...왜지?
왜지..?

6. 메인 메소드 실행

테스트 코드는 일단 통과했으니, Application.java에서 main 메소드를 실행해본다.(메인 왼쪽 실행 화살표 누르면 됨)
잘 실행된다.
톰캣 서버가 8080 포트로 실행되었다는 것도 로그에 출력된다.

7. 웹브라우저 실행

localhost:8080/hello로 접속
잘 된다.

0개의 댓글