좌선
좌선의 개발일지
좌선
전체 방문자
오늘
어제
  • 분류 전체보기 (79)
    • 개발환경 (3)
    • 알고리즘 (10)
      • 코딩테스트 (9)
      • 알고리즘 (1)
    • Java (54)
      • JPA (6)
      • Spring (5)
      • SpringBoot (15)
    • Network (2)
    • Database (1)
    • Git (2)
    • & (1)
    • Exception (3)
    • Study (0)
      • RealMySQL (0)
    • 회고 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • Spring Data JPA
  • 다트게임
  • Spring
  • Mustache
  • 스프링부트
  • 스프링 부트와 AWS로 혼자 구현하는 웹 서비스
  • 쿼리로그
  • programmers
  • TDD 실천법과 도구
  • dirtychecking
  • AWS
  • 코드로배우는스프링웹프로젝트
  • SpringBoot
  • 자바웹을다루는기술
  • 테스트주도개발
  • 자바 웹을 다루는 기술
  • 스프링부트와 AWS로 혼자 구현하는 웹 서비스
  • 머스테치
  • 더티체킹
  • 프로그래머스

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
좌선

좌선의 개발일지

[SpringBoot] 스프링부트 테스트 코드 작성하기
Java/SpringBoot

[SpringBoot] 스프링부트 테스트 코드 작성하기

2021. 7. 23. 18:41

스프링부트 실습 Chapter02 스프링 부트에서 테스트 코드를 작성하자

이동욱 作 '스프링 부트와 AWS로 혼자 구현하는 웹 서비스'

 

🔎 TDD와 단위 테스트란?

테스트 코드

TDD : 테스트가 주도하는 개발을 이야기한다.

단위 테스트 : TDD의 첫번째 단계인 기능 단위의 테스트 코드를 작성하는 것을 이야기한다.

 

테스트 코드를 작성하는 이유

코드 작성 후 톰캣 실행해서 결과 확인하는 개발 방식은 시간이 오래걸리고 매우 번거로움.

테스트 코드를 사용하게 되면 빠른 피드백과 자동검증이 가능하고 개발자가 만든 기능을 안전하게 보호해준다.

 

Hello Controller 테스트 코드 작성하기

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 읽기와 생성을 모두 자동으로 설정하고 @SpringBootApplication이 있는 위치부터 설정을 읽어가기 때문에 항상 프로젝트 최상단에 위치해야만 한다.

 

main 메소드에서 실행하는 SpringApplication.run으로 인해 내장 WAS를 실행한다. 때문에 서버에 톰캣을 설치하지 않아도 되고 스프링 부트로 만들어진 Jar파일로 실행하면 된다.

 

💡 기본 포트번호는 8080으로 되어있다.

혹시라도 오라클이 설치되어있다면 포트 중복으로 실행되지 않기 때문에 포트 번호를 변경해줘야 한다.

포트 번호 변경 방법

 

스프링 부트에서 내장 WAS를 사용하는 것을 권장하는 이유

' 언제 어디서나 같은 환경에서 스프링 부트를 배포 할 수 있기 때문 '

 

Controller

import com.jojoldu.book.springboot.web.dto.HelloResponseDto;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

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

    @GetMapping("/hello") // HTTP Method인 Get의 요청을 받을 수 있는 API를 만들어 줌
    public String hello() {
        return "hello";
    }

    @GetMapping("/hello/dto")
    public HelloResponseDto helloDto(@RequestParam("name") String name,
                                     @RequestParam("amount") int amount) {
        return new HelloResponseDto(name, amount);
    }
}

 

@RestController

JSON을 반환하는 컨트롤러로 만들어 준다.

 

@GetMapping

Http Method인 Get의 요청을 받을 수 있는 API를 만들어 준다.

예전에는 @RequestMapping(method = RequestMethod.GET)으로 사용되었음

 

@RequestParam

외부에서 API로 넘긴 파라미터를 가져오는 어노테이션

여기서는 외부에서 name (@RequestParam("name")) 이란 이름으로 넘긴 파라미터를 메소드 파라미터 name에 저장하게 됨.

 

🔎 스프링 부트 환경에서 테스트 코드를 작성하는 방법

src/test/java 디렉토리에 앞서 생성했던 패키지를 그대로 다시 생성해서 사용해준다.

일반적으로 테스트 클래스는 대상 클래스 이름에 Test를 붙임.

 

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.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class) // 스프링 부트 테스트와 Junit 사이에 연결자 역할
@WebMvcTest // Web에 집중할 수 있는 어노테이션 @Controller, @ControllerAdvice 등을 사용할 수 있으나
            // @Service, @Component, @Repository 등은 사용할 수 없다
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));
    }

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

        mvc.perform(
                    get("/hello/dto")
                            .param("name", name)
                            .param("amount", String.valueOf(amount)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.name", is(name)))
                .andExpect(jsonPath("$.amount", is(amount)));
    }
}

 

@RunWith(SpringRunner.class)

테스트를 진행할 때 JUnit에 내장된 실행자 외에 다른 실행자를 실행시킨다.

SpringRunner가 스프링 실행자. 스프링 부트 테스트와 JUnit 사이에 연결자 역할을 한다.

 

@WebMvcTest

스프링 테스트 어노테이션 중, Web에 집중할 수 있는 어노테이션

@Controller, @ControllerAdvice 등 사용 가능 , @Service, @Component, @Repository 사용 불가능

 

@Autowired

스프링이 관리하는 빈을 주입 받음

 

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"를 리턴하기 때문에 이 값이 맞는지 검증한다.

 

param

API 테스트할 때 사용될 요청 파라미터 설정

단, 값은 String만 허용

숫자/날짜 등의 데이터 등록시에는 문자열로 변경해야 사용가능함

 

jsonPath

JSON 응답값을 필드별로 검증할 수 있는 메소드

$를 기준으로 필드명을 명시

여기서는 name과 amount를 검증하니 $.name, $.amount로 검증

 

🔎 자바의 필수 유틸 롬복의 사용법

롬복

Getter, Setter, 생성자, toString을 어노테이션으로 자동 생성해준다.

 

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class HelloResponseDto {

    private final String name;
    private final int amount;

}

 

@Getter

선언된 모든 필드의 get 메소드를 생성해줌

 

@RequiredArgsConstructor

선언된 모든 final 필드가 포함된 생성자를 생성해줌

final이 없는 필드는 생성자에 포함되지 않는다.

 

롬복 테스트 코드

import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;

public class HelloResponseDtoTest {

    @Test
    public 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라는 테스트 검증 라이브러리의 검증 메소드

검증하고 싶은 대상을 메소드 인자로 받는다

메소드 체이닝이 지원되어 isEqualTo와 같이 메소드를 이어서 사용할 수 있다.

 

isEqualTo

assertj의 동등 비교 메소드

assertThat에 있는 값과 isEqualTo의 값을 비교해서 같을 때만 성공한다.

 

💡 테스트코드 실행 오류

그레들 버전으로 인해 생긴 오류

책에서는 그레들4로 사용했으나 나는 그레들 6.8 버전으로 테스트해서 해당 오류가 나타났다.

해당 오류는 build.gradle의 dependencies에

annotationProcessor('org.projectlombok:lombok')를 추가해주면 된다.

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.projectlombok:lombok')
    annotationProcessor('org.projectlombok:lombok')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

📢 https://github.com/jojoldu/freelec-springboot2-webservice/issues/2

 

P74 테스트코드에서 에러가 발생합니다. · Issue #2 · jojoldu/freelec-springboot2-webservice

HelloResponseDtoTest.java에서 메소드 실행 시 아래와 같은 에러가 발생합니다. Testing started at 오후 11:08 ... Task :cleanTest UP-TO-DATE Task :compileJava FAILED C:\Users\ssooy\Desktop\dev\springboot-book\src\main\java\c...

github.com

 

 

 

✨ 해당 실습 코드는 GitHub에 업로드 합니다.

    'Java/SpringBoot' 카테고리의 다른 글
    • [SpringBoot] 스프링부트 구글 로그인 연동하기
    • [SpringBoot] 템플릿 엔진 머스테치로 화면 구성하기
    • [SpringBoot] 스프링부트 JPA로 데이터베이스 다루기
    • [SpringBoot] Spring Data JPA 쿼리 로그 설정
    좌선
    좌선
    얼렁뚱땅 천방지축 굴러가는 개발자의 삶

    티스토리툴바