본문 바로가기

개발공부/웹개발

스프링 부트와 AWS로 혼자 구현하는 웹 서비스 (~77p)

* 테스트 코드에 대해 공부해보기

 

TDD란?

- 테스트가 주도하는 개발

- 테스트 코드먼저 작성하는 것 부터 시작

 

1. 항상 실패하는 테스트를 먼저 작성하고(RED)

2. 테스트가 통과하는 프로덕션 코드를 작성하고(GREEN)

3. 테스트가 통과하면 프로덕션 코드를 리팩토링합니다.(REFACTOR)

 

단위테스트란?

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

 

테스트코드의 작성이유?

- 초기에 문제 발견하도록 도와줌

- 기능에 대한 불확실성을 감소시킬 수 있음

- 단위테스트는 시스템에 대한 실제문서를 제공함(단위테스트 자체가 문서로 사용가능)

- 나중에 코드를 리팩토링하거나 라이브러리 업그레이드 등에서 기존 기능이 올바르게 작동하는지 확인 가능

 

기존 기능이 잘 작동되는것을 보장해주는것이 테스트 코드 **

 

가장 대중적인 테스트 프레임워크 : xUnit

- JUnit : Java

- DBUnit : DB

 

우리는 자바용인 Jnit 사용해볼것.

 


이제 실습 시작.

1. 프로젝트 생성

2. Application 클래스 생성

- 프로젝트의 main 클래스

- @SpringBootApplication으로 인해 스프링 부트의 자동설정, 스프링 Bean읽기와 생성을 모두 자동으로 설정.

- @SpringBootApplication이 있는 위치부터 설정을 읽음 => 프로젝트의 최상단에 위치해야만함

- SpringAppliction.run으로 내장 was 실행

 

* @RestController 

- 컨트롤러를 JSON을 반환하는 컨트롤러로 만들어줌

- 예전에는 @ResponseBody를 각 메소드마다 선언했던 것을 한번에 사용할 수 있게끔

 

* @GetMapping

- HTTPMethod인 Get의 요청을 받을 수 있는 Api를 만들어줌(받는 url 설정)

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

 

3. test코드 작성

 

* @RunWith(SpringRunner.class)

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

- 스프링부트 테스트와 JUnit 사이에 연결자 역할을 함

- 괄호안에 들어가있는 SpringRunner.class를 같이 실행

 

* @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를 검증

 

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

- mvc.perform의 결과를 검증

- 응답 본문의 내용을 검증

 

 

spring 뜨는것확인!

 

 

 

중간에 오류가 발생했는데 한글로 클래스명해서 나는 에러인듯

Execution failed for task ':test'.

No tests found for given includes : 

이런 에러가 발생하면 settings > Build, Execution, Deployment > Gradle

IntelliJ IDEA로 값을 바꿔주면된다.


롬복이란?

Lombok은  @어노테이션을 제공하고

이를 기반으로 반복 소스코드를 컴파일 과정에서 생성해주는 방식으로 동작하는 라이브러리

롬복 추가

- 롬복은 프로젝트마다 설정해야함

- 플러그인은 한번만 설치하면되지만 build.gradle에 라이브러리를 추가하는 것과 enable시키는 것은 프로젝트마다 설정

 

롬복으로 기존 소스 리팩토링

 

package com.springboot_book.first.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이 없는 필드는 생성자에 포함되지 않는다.

package com.springboot_book.first.web.dto;

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의 값을 비교해서 같을때만 성공

 

*** Junit의 기본 assertThat이 아닌 assertj의 assertThat을 사용한 이유

- CoreMathers와 달리 추가적으로 라이브러리가 필요하지않음

- 자동완성이 좀 더 확실하게 지원됨

 

* @RequestParam

- 외부에서 API로 넘긴 파라미터를 가져옴

- 외부에서 넘긴 파라미터를 메소드 파라미터에 저장하게 됨

 

@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)));
}

* param

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

- 값은 String만 허용되므로 숫자, 날짜모양의 데이터를 등록할때 문자열로 변경해야만 가능

 

* jsonPath

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

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