테스트 코드 작성하기

기능 단위의 테스트 코드 - 단위 테스트를 사용하였다
🔧테스트 도구 : JUnit5

단위테스트

TDD의 첫번째 단계

TDD와의 차이점
테스트 코드를 먼저 작성하지 않아도 되고, 리팩토링 포함 X

단위 테스트의 이점

  • 빠른 피드백
  • System.out.println()의 사용 대신 자동검증 가능함(Tomcat X)
  • 서비스의 각 기능을 안전하게 보호해줌
  • 새로운 기능이 추가될 때 기존 기능이 잘 작동되는 것을 보장해줌

Controller

@RestController
public class HelloController {

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

ControllerTest

@ExtendWith(SpringExtension.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));

    }
}    

1. @ExtendWith(SpringExtension.class)

JUnit4 @RunWith(SpringRunner.class)에서 수정

  • ExtendWith : 테스트 인스턴스의 lifecycle은 method or class. 확장을 위해 사용
  • SpringExtension.class : Spring TestContext Framework와 JUnit5를 연결

2. @WebMvcTest

여러 스프링 테스트 어노테이션 중, Web(Srping MVC)에 집중할 수 있는 어노테이션

사용 o@Controller, @ControllerAdvcie..
사용 x@Service, @Component, @Repository..

3. MockMvc

서블릿 컨테이너의 구동 없이 웹 애플리케이션을 서버에 배포하지 않고 스프링 MVC의 동작을 구현할 수 있는 클래스

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

MockMvc를 통해 /hello url로 HTTP GET 요청

perform()

  • MockMvc가 제공하는 method
  • RequestBuilder 객체를 인자로 받고 MockMvcRequestBuilders의 정적 메소드를 이용해서 생성

MockMvcRequestBuilders

  • GET, POST, PUT, DELETE 요청 방식과 매핑되는 get(), post(), put(), delete() 메소드를 제공
.andExpect(status().isOk())
  • mvc.perform의 결과를 검증
  • HTTP Header의 status를 검증(200,404,500..)
  • isOk() - 200인지 아닌지
.andExpect(content().string(hello));
  • mvc.perform의 결과 검증
  • content() - 응답 본문의 내용 검증
  • string(hello) - Controller에서 "hello"를 리턴하므로 이 값이 맞는지 검증

Lombok 롬복

개발할 때 자주 사용하는 코드 Getter, Setter, 생성자, toString 등을 어노테이션으로 자동 생성해줌

build.gradle

annotationProcessor 'org.projectlombok:lombok:1.18.20'
compileOnly 'org.projectlombok:lombok:1.18.20'

라이브러리 생성 후 플러그인 설치

리팩토링

DTO

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class HelloResponseDto {

    private final String name;
    private final int amount;
}

@RequiredArgsConstructor

  • 선언된 모든 final 필드가 포함된 생성자를 생성해줌
  • final이 없는 필드는 생성자에 포함되지 않음

lombok test

    @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() - assertThat에 있는 값과 isEqualTo값을 비교해서 같을 때만 성공

ControllerTest

    @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만 허용
  • String.valueOf(amount) - 숫자 문자열로 변경

jsonPath()

  • JSON 응답값을 필드별로 검증할 수 있는 메소드
  • $를 기준으로 필드명 명시



📄참고
https://itmore.tistory.com/entry/MockMvc-%EC%83%81%EC%84%B8%EC%84%A4%EB%AA%85
https://scshim.tistory.com/321
https://cheershennah.tistory.com/183

profile
개발 공부노트

0개의 댓글