스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - 2
02 스프링 부트에서 테스트 코드를 작성하자
2.1 테스트 코드 소개
TDD(Test Driven Development) 테스트-주도 개발
테스트-주도 개발의 기본 흐름은 실패하는 테스트를 작성하고, 테스트를 통과하는 가장 간단한 코드를 작성한 후, 리팩터링을 통해 중복을 제거하는 것이다.
단위 테스트 코드를 작성함으로써 얻는 이점
- 단위 테스트는 개발단계 초기에 문제를 발견하게 도와줍니다.
- 단위 테스트는 개발자가 나중에 코드를 리팩터링하거나 라이브러리 업그레이드 등에서 기존 기능이 올바르게 작동하는지 확인할 수 있습니다.(예, 회귀테스트)
- 단위 테스트는 기능에 대한 불확실성을 감소시킬 수 있습니다.
- 단위 테스트는 시스템에 대한 실제 문서를 제공합니다. 즉, 단위 테스트 자체가 문서로 사용할 수 있습니다.
2.2 Hello Controller 테스트 코드 작성하기
Application
클래스를 생성하자.
package com.jojoldu.book.springboot;
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);
}
}
Application
클래스는 앞으로 만들 프로젝트의 메인클래스가 된다.
@SpringBootApplication
으로 스프링 부트의 자동 설정, 스프링 Bean 읽기와 생성을 모두 자동으로 설정해준다. 이 클래스는 현재 자신의 클래스가 있는 위치부터 설정을 읽어가기 때문에 프로젝트의 최상단에 위치하도록 하는게 편하다.
main
메서드에서 실행하는 SpringApplication.run
으로 인해 내장 WAS(Web Application Server, 웹 애플리케이션 서버)를 실행한다.
내장 WAS를 통해 애플리케이션을 실행하면 서버에 톰캣을 설치할 필요가 없게 되고, 스프링 부트로 만들어진 Jar파일로 실행하면 된다.
HelloController
클래스를 생성하자.
package com.jojoldu.book.springboot.web;
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
@ResponsBody
와@Controller
를 합친 어노테이션이라 생각하면된다.- JSon을 반환하는 컨트롤러로 만들어준다.
@GetMapping
- Http Method인 Get의 요청을 받을 수 있는 API로 만들어준다.
HelloControllerTest
클래스를 생성하자.
테스트 클래스를 직접 생성하는 방법도 있고 커맨드+쉬프트+T(⌘+⇧+T)
를 통해 생성하는 방법도 있다.
package com.jojoldu.book.springboot.web;
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;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = HelloController.class)
class HelloControllerTest {
@Autowired
private MockMvc mvc;
@Test
void hello가_리턴된다() throws Exception {
String hello = "hello";
mvc.perform(get("/hello"))
.andExpect(status().isOk())
.andExpect(content().string(hello));
}
}
*참고: JUnit5를 통한 테스트 코드 작성이라 책과는 약간 다르다.
@WebMvcTest
- 여러 스프링 테스트 어노테이션 중, Web(Spring MVC)에 집중할 수 있는 어노테이션이다.
- 위 어노테이션을 선언하므로
@controller
,@ControllerAdvice
등을 사용할 수 있다. - 단,
@Service
,@Component
,@Repository
등은 사용할 수 없다.
@ExtendWith(SpringExtension.class)
- JUnit5에서 RunWith(SpringRunner.class) 대신 사용하는 어노테이션이다.
- 스프링 부트 테스트와 JUnit 사이에 연결자 역할을 한다.
Autowired
- 스프링이 관리하는 빈(Bean)을 주입 받는다.
private MockMvc mvc
- 웹 API를 테스트할 때 사용한다.
- 스프링 MVC 테스트의 시작점이다.
mvc.perform(get("/hello"))
- MockMvc를 통해 /hello 주소로 HTTP GET 요청을 한다.
- static import를 통해 get이라고 짧게 줄일 수 있었다. import를 확인하자.
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
andExpect(status().isOk())
- mvc.perform의 결과를 검증한다.
- HTTP Header의 status를 검증한다.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
andExpect(contetn().string(hello))
- 응답 본문의 내용을 검증한다.
- Controller에서 "hello"를 리턴하기 때문에 이 값이 맞는지 검증한다.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
2.3 롬복 소개 및 설치하기
롬복은 자바 개발 시 자주 사용하는 코드 Getter, Setter, 기본생성자, toString 등을 어노테이션으로 자동 생성해 준다.
build.gradle의 dependencies
를 변경하자.
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web')
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation('org.projectlombok:lombok')
testImplementation 'org.springframework.boot:spring-boot-starter-test'
annotationProcessor 'org.projectlombok:lombok'
}
2.4 Hello Controller 코드를 롬복으로 전환하기
HelloResponseDto 클래스를 생성하자.
package com.jojoldu.book.springboot.web.dto;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public class HelloResponseDto {
private final String name;
private final int amount;
}
@Getter
- 선언된 모든 필드의 get 메소드를 생성해 준다.
@RequiredArgsConstructor
- 선언된 모든 final 필드가 포함된 생성자를 생성해 준다.
- final이 없는 필드는 생성자에 포함되지 않는다.
HelloResponseDtoTeset를 생성하자
package com.jojoldu.book.springboot.web.dto;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
class HelloResponseDtoTest {
@Test
void 롬복_기능_테스트() {
//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);
}
}
assertThat
- assertj라는 테스트 검증 라이브러리의 검증 메소드다.
- 검증하고 싶은 대상을 메서드 인자로 받는다.
HelloController에 HelloResponseDto를 사용하도록 코드를 추가하자.
@GetMapping("/hello/dto")
public HelloResponseDto helloDto(
@RequestParam("name") String name, @RequestParam("amount") int amount) {
return new HelloResponseDto(name, amount);
}
@RequestParam
- 외부에서 API로 넘긴 파라미터를 가져오는 어노테이션이다.
HelloControllerTest에 테스트를 추가하자
package com.jojoldu.book.springboot.web;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = HelloController.class)
class HelloControllerTest {
@Autowired
private MockMvc mvc;
@Test
void hello가_리턴된다() throws Exception {
...
}
@Test
void helloDto가_리턴된다() throws Exception {
String name = "hello";
int amount = 1000;
mvc.perform(get("/hello/dto")
.param("name", name)
.param("amount", String.valueOf(amount)))
.andExpect(jsonPath("$.name", is(name)))
.andExpect(jsonPath("$.amount", is(amount)));
}
}
param
- API 테스트할 때 사용될 요청 파라미터를 설정한다.
- 단, 값은 String만 허용!
jsonPath
- JSON 응답값을 필드별로 검증할 수 있는 메서드이다.
- $를 기준으로 필드명을 명시한다.
static import 참고
is
-> import static org.hamcrest.Matchers.is;
jsonPath
-> import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
참고
- 테스트 코드에서 static import를 통해 줄여진 메서드명이 많다.
- 빨간줄이 뜬다고 당황하지말고 import해주자.
- build.gradle에 dependencies에서
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
를 꼭 제거해주자! 그렇지 않으면 테스트코드 실행 시 에러가 발생한다!
Author And Source
이 문제에 관하여(스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - 2), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kimjinwook/스프링-부트와-AWS로-혼자-구현하는-웹-서비스-2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)