notepad by Oxix

스프링부트에서 테스트 코드 작성하기-1 본문

Spring-boot

스프링부트에서 테스트 코드 작성하기-1

Oxix 2022. 6. 29. 14:28

먼저 알아야할 것은 TDD와 단위 테스트는 다른 것이다. TDD는 테스트가 주도하는 개발을 의미하며 테스트 코드를 먼저 작성하는 것 부터 시작한다. -> 작성 종료 조건을 먼저 정해놓고 코딩을 시작한다고 생각하면 된다.

 

  • RED  : 항상 실패하는 테스트 작성
  • GRREN : 테스트에 통과하는 프로덕션 코드 작성
  • REFACTOR : 테스트가 통과하면 프로덕션 코드를 리팩터링 -> 보다 더 효율적인 방법으로 개선

위의 과정을 반복하며 제대로 동작하는지 확인한다.

반면 단위 테스트는 TDD의 첫 단계인 기능 단위의 테스트 코드를 작성하는 것을 의미한다. 순수하게 테스트 코드만 작성하는 것을 뜻한다. 

사용이유

  • 개발 단계 초기에 문제를 발견하게 해준다.
  • 기능에 대한 불확실성을 감소시켜준다.
  • 추후에 코드를 리팩터링하거나 라이브러리 업그레이드 등에서 기존 기능이 올바르게 작동하는지 확인 가능하다.
  • 단위 테스트는 시스템에 대한 실제 문서를 제공한다. 즉, 단위 테스트 자체가 문서로 사용될 수 있다.

 

Hello Controller 테스트 코드 작성하기 

일반적으로 패키지명은 웹 사이트 주소의 역순으로 한다. 예를 들어 demo.example.com 이라는 사이트라면 패키지명은 com.example.demo으로 하면 된다.

클래스의 코드는 다음과 같다.

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;  @SpringBootApplication public class DemoApplication {  	public static void main(String[] args) { 		SpringApplication.run(DemoApplication.class, args); 	} } 

 

위의 코드는 프로젝트의 메인 클래스가 된다. @SpringBootApplication으로 인해 스프링 부트의 자동 설정, 스프링 Bean 읽기와 생성을 모두 자동으로 설정된다. @SpringBootApplication이 있는 위치부터 설정을 읽어가기 때문에 이 클래스는 항상 프로젝트의 최상단에 위치해야만 한다.

main 메서드에서 실행하는 SpringApplication.run으로 인하여 내장 WAS를 실행한다. 내장 WAS란? 별도로 외부에 WAS를 두지 않고 애플리케이션을 실행할 때 내부에서 WAS를 실행하는 것을 의미한다. 이렇게 되면 톰캣을 설치할 필요가 없게 되고, 스프링 부트로 만들어진 Jar 파일로 실행하면 된다.

스프링 부트에서는 내장 WAS를 사용하는 것을 권장하고 있다. 이유는 언제 어디서나 같은 환경에서 스프링 부트를 배포 할 수 있기 때문이다. 

외장 WAS를 사용한다고 하면 모든 서버는 WAS의 종류와 버전, 설정을 일치 시켜야 하지만 내장 WAS를 사용할 경우 해당 문제를 모두 해결 가능하다. 그렇기에 많은 회사에서 내장 WAS를 사용하도록 전환하고 있다.

web이라는 하위 패키지를 만들고 간단한 API를 만드려고한다. 컨트롤러와 관련된 클래스들은 모두 해당 패키지에 담는다.

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";     } } 
  • @RestController : 컨트롤러를 JSON으로 반환하는 컨트롤러로 만들어 준다.
  • @GetMapping : HTTP Method의 GET의 요청을 받을 수 있는 API를 만들어 준다.

작성한 코드가 제대로 작동하는지 테스트를 하기 위해 WAS를 실행하지 않고 테스트 코드로 검증하려면 src/test/java 디렉토리 앞에서 생성했던 패키지를 그대로 다시 생성이후 코드를 추가한다.

package com.example.demo;   import com.example.demo.web.HelloController; 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;  @RunWith(SpringRunner.class) @WebMvcTest(controllers = HelloController.class) public class HelloControllerTest {      @Autowired     private MockMvc mvc;      @Test     public void printHello() throws Exception {         String hello = "hello";          mvc.perform(get("/hello")).andExpect(status().isOk()).andExpect(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(get("/hello"))

  • MockMvc를 통해 /hello 주소로 HTTP GET 요청을 한다.
  • 체이닝이 지원되어 아래와 같이 여러 검증 기능을 이어서 선언할 수 있다.

.andExpect(status().isOk())

  • mvc.perform의 결과를 검증한다.
  • HTTP Header의 Status를 검증한다.
  • 우리가 흔히 알고 있는 200, 404, 500 등의 상태를 검증한다.
  • 여기서 OK -> 200인지 아닌지를 검증하게 된다.

.andExpect(content().string(hello))

  • mvc.perform의 결과를 검증한다.
  • 응답 본문의 내용을 검증한다.
  • Controller에서 "hello"를 리턴하기 때문에 이 값이 맞는지 검증한다.

테스트를 마치고 실행을 해보면 localhost:8080/hello로 접속했을 때 다음과 같이 나오는 것을 확인할 수 있다.

브라우저로 한 번씩 검증은 하되, 테스트 코드는 꼭 따라 하는 습관을 가져야 견고한 소프트웨어를 만드는 역량이 성장할 수 있다. 추가로, 절대 수동으로 검증하고 테스트 코드를 작성하진 않는다. 검증 이후 정말 못 미더울때 프로젝트를 실행해 확인해야한다.

 

참조

TDD(Test-Driven Development)란?
1. TDD란? TDD(Test-Driven Development)는 말 그대로 "테스트 주도 개발: 테스트가 개발을 이끌어 나간다."라고 정의할 수 있다. 메소드 나 함수 같은 프로그램 모듈을 작성할 때 ‘작성 종료조건을 먼저 정해놓..
hyem-study.tistory.com