개발자의 서재

Chapter.02 : 스프링부트에서 테스트 코드를 작성하자. 본문

SpringBootProject/SpringBoot_ Oauth_AWS

Chapter.02 : 스프링부트에서 테스트 코드를 작성하자.

ironmask431 2022. 2. 11. 22:57

"스프링부트와 AWS로 혼자 구현하는 웹 서비스" 라는 책을 바탕으로 학습목적의 프로젝트를 진행하고 있습니다. 

 

소스 : https://github.com/ironmask431/springboot_aws_01

Chapter 02. 스프링 부트에서 테스트 코드를 작성하자

2.1 테스트코드 소개

TDD : 테스트가 주도하는 개발 RED - 항상 실패하는 테스트 작성 GREEN - 테스트가 통과하는 프로덕션 코드를 작성 REFECTOR - 테스트가 통과하면 프로덕션 코드를 리팩토링

단위테스트는 TDD 의 첫번째 단계인 기능단위의 테스트코드를 작성하는것을 말함.

단위테스트의 장점 (위키디피아)

  • 단위테스트는 개발초기에 문제를 발견하도록 도와줌
  • 단위테스트는 개발자가 나중에 코드를 리팩토링하거나 라이브러리 업그레이드 등에서 기존기능이 올바르게 작동하는지 확인할수있다.
  • 단위테스트는 기능에 대한 불확실성을 감소시킬수있다.
  • 단위테스트는 시스템에대한 실제 문서를 제공한다. 단위테스트 자체가 문서로 사용가능하다.

1.첫번째장점. 빠른 피드백

단위테스트가 없을때 개발방법

1.코드작성
2.tomcat 구동
3.postman 같은 API도구로 HTTP요청
4.요청결과를 print로 확인
5.결과가 다르면 tomcat을 중지하고 코드수정

기존방식은 매번 코드를 수정할때마다 tomcat을 재구동해야함. 구동에만 수시간을 소비할수있음.
단위테스트는 매번 tocmat을 재구동할필요없다.

 

2.두번째장점. 자동검증 가능. 기존방식은 print 된 요청결과를 눈으로 직접 확인 해야하지만 단위테스트는 수동검증이 필요없게됨.

 

3.세번째장점. 개발자가 만든기능을 안전하게 보호

b라는 기능을 추가햇더니 기존 a기능에 문제가 생김. 매번 모든 서비스를 테스트 할 순없음.
새로운기능이 추가될때 기존 기능이 잘작동되는것을 보장해준다.
단위테스트는 100%익혀야할 기술이자 습관이다.
테스트코드 작성을 도와주는 프레임워크들

java - JUNIT

2.2 Hello Controller 테스트코드 작성하기

Application.java 작성 (springBoot 내장was 구동 컨트롤러)

//Application : 메인클래스
//@SpringBootApplication : 스프링부트의 자동설정, 스프링 bean 읽기와 생성 자동설정
//이 어노테이션이 있는 위치부터 설정을 읽어가기 때문에 이 클래스는 항상 프로젝트 최상단에 위치해야함.
@SpringBootApplication
public class Application {
    public static void main(String[] args){
        //스프링부트 내장was 실행
        SpringApplication.run(Application.class, args);
    }
}

HelloController.java 생성 (간단한 get ('/hello') 요청을 받는 컨트롤러)

//@RestController = 컨트롤러를 json을 반환하는 컨트롤러로 만들어줍니다.
//예전에는 @ResponseBody를 각 메소드마다 선언했던것을 한번에 사용 할 수 있도록 해줍니다.
@RestController
public class HelloController {

    //@GetMapping = http method인 get의 요청을 받을 수 있는 api를 만들어줍니다.
    //예전에는 @RequestMapping(method=RequestMethod.GET) 으로 쓰이던것.
    @GetMapping("/hello")
    public String Hello(){
        return "hello";
    }
}

HelloControllerTest.java 생성 (HelloController의 '/hello' get요청 테스트 클래스)

@RunWith(SpringRunner.class) //테스트를 진행할 Junit에 내장된 실행자
@WebMvcTest(controllers = HelloController.class) //여러 스프링테스트 어노테이션중 web mvc에 집중할 수 있는 어노테이션
public class HelloControllerTest {

    //@Autowired = spring이 관리하는 bean을 주입
    @Autowired
    private MockMvc mvc; //웹api를 테스트할 때 사용, 스프림mvc테스트의 시작점. get,post등에대한 api테스트 가능

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

        //MockMvc를 통해 /hello 주소로 get요청을함.
        mvc.perform(get("/hello"))
                .andExpect(status().isOk()) 
                //mvc.perform 의 결과검증. (http헤더의 status가 200 인지 확인)
                .andExpect(content().string(hello)); 
                //mvc.perform 의 결과검증. 응답본문의 내용이 hello가 맞는지 검증
    }
}

테스트 컨트롤러 생성 후 테스트 메소드 실행 > "Tests passed : 1" 테스트통과메세지 확인

Application.java 톰캣 구동 후 localhost:8080/hello 실제 테스트시 hello 정상 노출 확인함.

2.3 롬복 소개 및 설치하기

자바개발자의 필수라이브러리 롬복
롬복은 getter, setter 등을 어노테이션으로 자동생성해줌

1.build.gradle 에 롬복추가

//dependencies 에 추가
implementation('org.projectlombok:lombok')

저장 후 gradle 탭에서 rombok 추가된것 확인

 

2.lombok 플러그인설치

확인해보니 이미 설치되어있음. (저번에 설치한듯)

2.4 HelloController 코드를 롬복으로 전환하기

1.HelloResponseDto.java 클래스 생성

@Getter
// 선언된 모든 필드의 get메소드를 생성해줍니다.
@RequiredArgsConstructor
//선언된 모든 final 필드가 포함된 생성자를 생성해줍니다.
//final이 없는 필드는 생성자에 포함되지 않습니다.
public class HelloResponseDto {
    private final String name;
    private final int amount;
}

2.HelloResponseDtoTest.java 테스트 클래스 생성 / 테스트 코드 실행

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 : assertj 의 동등 비교 메소드
    }
}

생성자를 못찾고 있다고함. 구글링해보니 gradle 버전 5.x 부터는 build.gradle 에 추가설정을 해줘야한다고함

//build.gradle > dependencies 에 추가    
annotationProcessor('org.projectlombok:lombok')   
testAnnotationProcessor('org.projectlombok:lombok')

3.Test passed: 1 테스트 정상 실행 확인

4.HelloController.java 에 "/hello/dto" mapping 추가

@GetMapping("/hello/dto")
public HelloResponseDto helloDto(@RequestParam("name") String name, @RequestParam("amount") int amount){
    //@RequestParam("name") String name : request로 받은 param 값 name을 인자로 받음.
    return new HelloResponseDto(name, amount);
}

5.HelloControllerTest.java 에 helloDto 테스트메소드 추가

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

    mvc.perform(get("/hello/dto")
        .param("name",name) //api테스트시 사용될 요청파라미터 설정 (String만 허용)
        .param("amount",String.valueOf(amount)))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$.name",is(name)))//api의 json응답값을 필드별로 검증
        .andExpect(jsonPath("$.amount",is(amount)));
}

6.Test passed: 1 테스트 정상 실행 확인

Comments