이번에 나는 단위 테스트 코드만 한다.
테스트 코드는 왜 작성해야 할까?
- 단위 테스트 코드 이점
개발단계 초기 문제 발견 도움
리팩토링, 라이브러리 업그레이드 등에서 기존 기능 작동 확인 가능(ex. 회귀 테스트)
기능에 대한 불확실성 감소
시스템에 대한 실제 문서 제공(단위 테스트 자체가 문서로 사용)
테스트 코드는 이런 번거로움을 해결할 수 있다.
테스트 코드 작성을 도와주는 프레임워크로 xUnit이 가장 대중적이다.
나는 자바용인 JUnit을 사용한다.(JUnit4)
Java 디렉토리에 패키지를 생성한다.
com.springboot.example.project1로 생성해주었다.
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);
}
}
앞으로 컨트롤러와 관련된 클래스들은 모두 이 패키지에 담게 된다.
간단한 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";
}
}
먼저 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 오류가 떴다.
뭔지 몰라서 프로젝트 갈아엎고 하다가 그레이들 버전 문제인가? 했다.
근데 깃에 커밋과 푸시를 하고 테스트 실행하니까 된다...왜지?
왜지..?
테스트 코드는 일단 통과했으니, Application.java에서 main 메소드를 실행해본다.(메인 왼쪽 실행 화살표 누르면 됨)
잘 실행된다.
톰캣 서버가 8080 포트로 실행되었다는 것도 로그에 출력된다.
localhost:8080/hello로 접속
잘 된다.