[스프링 부트와 AWS로 혼자 구현하는 웹 서비스]무작정 따라하기 2일차

민지킴·2021년 3월 27일
0
post-thumbnail

*모든 내용은 책에 있는 내용을 기반으로 작성하였습니다.

2장 ----

2.1 테스트 코드 소개

TDD와 UnitTest(단위 테스트)

TDD

테스트가 주도하는 개발, 테스트 코드를 먼저 작성한다.

레드 그린 사이클이라는 것이있다.

항상 실패라는 테스트를 먼저 작성하고(Red) ->

테스트가 통과하는 프로덕션 코드를 작성하고(Green) ->

테스트가 통과하면 프로덕션 코드를 리팩토링한다.(Refactor)

단위 테스트

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

순수하게 테스트 코드만 작성하는것을 이야기한다.

장점

  • 단위 테스트는 개발단계 초기에 문제를 발견하게 도와준다.

  • 단위 테스트는 개발자가 나중에 코드를 리팩토링 하거나 라이브러리 업그레이드 등에서
    기존 기능이 올바르게 작동하는지 확인할 수 있다. (ex. 회귀테스트)

  • 단위 테스트는 기능에 대한 불확실성을 감소 시킬 수 있다.

  • 단위 테스트는 기능에 대한 불확실성을 감소시킬 수 있습니다.

  • 단위 테스트는 시스템에 대한 실제 문서를 제공한다. 단위 테스트 자체가 문서로 사용될 수 있다.

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

일반적으로 패키지명은 웹 사이트 주소의 역순이다.

웹사이트 주소가 admin.jojoldu.com 이라면

패키지명은 com.jojoldu.admin 이다.

Application.java

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

메인 클래스 역할을 한다.

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

main 메소드 안에 SpringApplication.run으로 인해 내장 WAS를 실행한다.
내장WAS : Web Application Server - 별도로 외부에 WAS를 두지 않고 애플리케이션을 실행할 때 내부에서 WAS를 실행하는 것

이렇게 되면 항상 서버에 Tomcat을 설치할 필요가 없어지며, 스프링 부트에서 만들어진 Jar파일로 실행하면 된다. (Jar : 실행가능한 java 패키징 파일)

언제 어디서나 같은 환경에서 스프링 부트를 배포할 수 있기에 사용 권장
외장 WAS 를 사용하게 된다면 모든 서버는 WAS의 종류와 버전, 설정을 일치시켜야만 하므로 모든 서버가 같은 환경을 구축해야만 해서 힘들어진다.

HelloController

package com.jojoldu.book.springboot.web;

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  // (1)
public class HelloController {

    @GetMapping("/hello") // (2)
    public String hello(){
        return "hello";
    }

}

(1) RestController

  • 컨트롤러를 JSON으로 반환해주는 컨트롤러로 만든다.

(2) GetMapping

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

Test 코드를 만들때는 src/test/java에 같은 패키지 이름으로 다시 만들어주며
class이름은 대상 클래스 이름에 Test를 붙인다.

HelloControllerTest

package com.jojoldu.book.springboot.web;


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.*;
import static org.hamcrest.Matchers.is;

@RunWith(SpringRunner.class) // (1)
@WebMvcTest(controllers = HelloController.class) // (2)
public class HelloControllerTest {

    @Autowired // (3)
    private MockMvc mvc; // (4)

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

        String hello = "hello";

        mvc.perform(get("/hello")) // (5)
                .andExpect(status().isOk()) // (6)
                .andExpect(content().string(hello)); // (7)
    }

}

(1) RunWith(SpringRunner.class)

  • 테스트를 진행할때 JUnit에 내장된 실행자 외에 다른 실행자를 실행시킨다.
  • 여기서는 SpringRunner라는 스프링 실행자를 사용한다.
  • 즉, 스프링 부트 테스트와 JUnit 사이에 연결자 역할을 한다.

(2) WebMvcTest

  • 여러 스프링 테스트 어노테이션 중, Web(Spring Mvc)에 집중할 수 있는 어노테이션이다.
  • 선언할 경우 @Controller, @ControllerAdvice 등을 사용할 수 있다.
  • 단 @Service, @Component, @Repository 등은 사용할 수 없다.
  • 여기서는 컨트롤러만 사용하기 때문에 선언한다.

(3) Autowired

  • 스프링이 관리하는 빈(Bean)을 주입받는다.

(4) private MockMvc mvc

  • 웹 API 를 테스트 할때 사용한다.
  • 스프링 MVC 테스트의 시작점이다.
  • 이 클래스를 통해 HTTP, GET, POST 등에 대한 API를 테스트를 할 수 있습니다.

(5) mvc.perform(get("/hello"))

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

(6) .andExpect(status.isOk())

  • mvc.perform의 결과를 검증한다.
  • HTTP Header의 Status를 검증한다.
  • 200, 404, 500 등의 상태를 검증
  • 여기서는 200인지 아닌지 즉 Ok인지 검증

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

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

2.3

책의 내용 따름

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

HelloResponseDtoTest

package com.jojoldu.book.springboot.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); // (1), (2)
        assertThat(dto.getAmount()).isEqualTo(amount);

    }
}

(1) assertThat

  • assertj라는 테스트 검증 라이브러리의 검증 메소드이다.
  • 검증하고 싶은 대상을 메소드 인자로 받는다.
  • 메소드 체이닝이 지원되어 isEqualTo와 같이 메소드를 이어서 사용할 수 있다.

(2) isEqualTo

  • assertj의 동등 비교 메소드이다.
  • assertThat에 있는 값과 isEqualTo의 값을 비교해서 같을 때만 성공이다.

Junit 의 assertThat VS assertj의 assertThat

*assertj의 장점 : 추가적으로 라이브러리가 필요하지 않고, 자동완성이 더 확실하게 지원된다.

HelloController

package com.jojoldu.book.springboot.web;

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
public class HelloController {

    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }

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

}

(3) RequestParam

  • 외부에서 API로 넘긴 파라미터를 가져오는 어노테이션이다.
  • 여기서는 외부에서 name 이란 이름으로 넘긴 파라미터를 메소드 파라미터(String name)에 저장한다.

HelloControllerTest

package com.jojoldu.book.springboot.web;


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.*;
import static org.hamcrest.Matchers.is;

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = HelloController.class)
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).    // (1)
        param("amount",String.valueOf(amount)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.name", is(name))) // (2)
                .andExpect(jsonPath("$.amount",is(amount)));
    }

}

(1) param

  • API 테스트할 떄 사용될 요청 파라미터를 설정한다.
  • String 값만 허용한다.
  • 숫자, 날짜 등은 문자열로 바꿔야한다.

(2) jsonPath

  • JSON 응답값을 필드별로 검증할 수 있는 메소드이다.
  • $를 기준으로 필드명을 명시한다.
  • 여기서는 name, amount를 검증한다.
profile
하루하루는 성실하게 인생 전체는 되는대로

0개의 댓글