[Spring] 2장 스프링 부트에서 테스트 코드 작성

Date:

카테고리:

2장 - 스프링 부트에서 테스트코드를 작성하자

2.1 테스트 코드 소개

  • TDD : 테스트 코드를 먼저 작성하는 것부터 시작, 즉 테스트가 주도하는 개발(실패하는 테스트 먼저 작성, 테스트가 통과하는 프로덕션 코드 작성, 통과하면 프로덕션 코드를 리팩토링)
  • Unit Test : 기능 단위의 테스트 코드를 작성하는 것


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

1
2
3
4
5
6
7
8
9
10
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Spring2Application {

	public static void main(String[] args) {
		SpringApplication.run(Spring2Application.class, args);
	}
}
  1. @SpringBootApplication : 으로 인해 스프링 부트의 자동 설정, Bean 읽기와 생성을 모두 자동으로 설정
  2. SpringApplication.run() : 으로 인해 내장 Web Application Server를 실행 항상 서버에 톰캣을 설치할 필요 없고, 스프링 부트로 만들어진 Jar 파일(실행가능한 Java 패키징 파일)로 실행하면 됨.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// web/HelloController

@RestController
public class HelloController {

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

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

        return new HelloResponseDto(name, amount);
    }

}
  1. @RestController : 컨트롤러를 JSON 반환하는 컨트롤러로 만들어준다.
    1. 이전 인프런 강의 때 배웠던 것 잠깐!
    2. [Spring] Restful한 스프링 @ResponseBody vs @RestController

스크린샷 2022-11-18 오후 1 46 06

  1. @GetMapping : HTTP Method인 Get의 요청을 받을 수 있는 API
    GET vs POST
    • GET

      1. 클라에서 서버로 어떤 리소스로부터 정보를 요청하기 위해 사용
      2. 데이터를 읽거나 검색할 때(조회)
      3. 요청을 전송할 때 URL 주소 끝에 파라미터로 포함되어 전송, 이 부분을 QueryString이라고 함
      4. 민감한 데이터를 다룰 때 GET 요청을 사용하면 안됨
    • POST

      1. 리소스를 생성/업데이트 하기 위해 서버에 데이터를 보내는 데 사용
      2. 전송해야될 데이터를 HTTP 메세지의 Body에 담아서 전송
      3. 길이의 제한 없이 데이터 전송 가능
      4. 데이터가 Body로 전송되고 내용도 눈에 안 보여서 GET보다 보안적으로 안전하다고 생각할 수 있지만 POST도 확인할 수 있기에 민감한 데이터의 경우 반드시 암호화 하기



✅ 테스트 - HelloControllerTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RunWith(SpringRunner.class)
@WebMvcTest
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));
    }

2.3 롬복 소개 및 설치하기

롬복은 자바 개발 시 자주 사용하는 코드인 Getter, Setter, 기본 생성자, toString등을 어노테이션으로 자동 생성

1
2
3
dependencies {
	implementation 'org.projectlombok:lombok'
}


Preferences > Build, Execution, Deployment > Compiler > Annotation Processors 에서

  • Enable annotation processing 체크해주기
  • build.gradle에 라이브러리 추가와 위의 체크는 프로젝트마다 진행해야 함.


2.4 Hello Controller 코드를 롬복으로 전환

1
2
3
4
5
6
7
@Getter
@RequiredArgsConstructor
public class HelloResponseDto {

    private final String name;
    private final int amount;
}
  1. @Getter : 선언된 모든 필드의 get메소드 생성
  2. @RequiredArgsConstructor : 선언된 모든 final 필드가 포함된 생성자를 생성


HelloController에도 새로 만든 ResponseDto를 사용하도록 코드를 추가해보자

1
2
3
4
5
6
@GetMapping("/hello/dto")
    public HelloResponseDto helloDto(@RequestParam("name") String name,
                                     @RequestParam("amount") int amount) {

        return new HelloResponseDto(name, amount);
    }
  • @RequestParam : 외부에서 API로 넘긴 파라미터를 가져옴
  • @RequestParam(“amount”) 외부에서 amount란 이름으로 넘긴 파라미터를 메소드 파라미터 amount (int amount)에 저장


✅ 테스트 - HelloControllerTest

1
2
3
4
5
6
7
8
9
10
11
12
13
@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)));
    }
  1. .param : API 테스트할 때 사용될 요청 파라미터를 설정, String만 허용되기에 숫자/날짜 데이터 등록시 문자열로 변경하자
  2. jsonPath : JSON 응답값을 필드별로 검증할 수 있음, $을 기준으로 필드명 명시




JUnit4와 JUnit5의 혼용으로 인한 경고 해결

[JUnit] 경고: Runner org.junit.internal.runners.ErrorReportingRunner

  • junit5에서는 @RunWith 어노테이션을 지원X → 대신 @ExtendWith 지원
    • 따라서 org.junit.jupiter.api.Test 을 사용할 경우에는 @ExtendWith 사용
  • junit4를 사용하려면 org.junit.jupiter.api.Test -> import org.junit.Test; 으로 변경!




DTO, DAO, VO란?

  1. DTO(Data Transfer Object)는 계층 간 데이터 교환을 하기 위해 사용하는 객체로, DTO는 로직을 가지지 않는 순수한 데이터 객체(getter, setter만 가진 클래스)
  2. DAO(Data Access Object)는 데이터베이스의 data에 접근하기 위한 객체로, 데이터베이스에 접근하기 위한 로직과 비즈니스 로직을 분리하기 위해 사용
    1. 보통 ibatis나 MyBatis 등에서 DAO라보 불리는 DB Layer 접근자임. JPA에선 Repository라고 부르며 인터페이스로 생성
    2. spring boot 에선 → ~Repository라고 인터페이스 생성 후 JpaRepository<Entity 클래스, PK 타입> 을 상속하면 기본 CRUD 메소드가 자동으로 생성
  3. VO(Value Object)는 값을 위해 쓰이며 사용하는 도중에 변경 불가능하고 오직 읽기만 가능한 read-Only 특징을 가진다. DTO와 유사하지만 DTO는 setter를 가지고 있어서 값 변경 가능

Date:

댓글남기기