스프링부트에서 테스트 코드 작성하기 (1)

박의진·2023년 6월 20일
0

스프링부트

목록 보기
2/7
post-custom-banner

TDD와 단위테스트

1) TDD 란?

  • 테스트가 주도하는 개발을 의미한다.
  • 테스트 코드를 먼저작성하는 것 부터 시작

2) 단위테스트란?

  • TDD의 첫번째 단계인 기능 단위으 테스트 코드를 작성하는 것을 의미
  • TDD와 달리 테스트코드를 꼭 먼저 작성해야하는 것도 아니고, 리팩토링도 포함되지 않음
  • 순수하게 코드를 작성하는 것을 의미

테스트 코드를 작성해야 하는 이유

1) 단위테스트는 개발단계 초기에 문제를 발견하게 도와줌
2) 개발자가 나중에 코드를 리팩토링하거나 라이브러리 업그레이드 등에서 기존 기능이 올바르게 작동하는지확인할 수 있음

Hello Controller 테스트 코드 작성하기

1) Application 클래스 작성하기

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • 프로젝트의 메인 클래스
  • @SpringBootApplication로 인해 스프링 부트의 자동설정, 스프링 Bean 읽기와 생성을 모두 자동으로 설정
  • @SpringBootApplication 이 있는 위치부터 설정을 읽어가기 때문에 이 클래스는 항상 프로젝트의 최상단에위치해야만 함
  • main에서 실행하는 SpringApplication.run으로 인해 내장 WAS를 실행함
  • 내장 WAS 실행 시 서버에 톰캣을 항상 설치할 필요가 없게되고, 스프링부트로 만들어진 Jar 파일로 실행하면 됨

2) web 패키지안에 HelloController 생성

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }
}
  • RestController
    • 컨트롤러를 JSON을 반환하는 컨트롤러로 만들어 줌
    • @ResponseBody를 각 메소드마다 선언했던 것을 한번에 사용할 수 있게 해줌
  • GetMapping
    • HTTP 메소드인 GET의 요청을 받을 수 있는 API를 만들어 줌
    • 예전에는 RequesetMapping(method = RequestMethod.GET)으로 사용
    • 이제는 /hello로 요청이 오면 hello를 반환하는 기능을 가짐

3) 테스트 패키지 밑에 WEB 패키지 밑에 HelloControllerTest 클래스 생성

@RunWith(SpringRunner.class)
@MockBean(JpaMetamodelMappingContext.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));
    }
   }
  • @RunWith(SpringRunner.class)

    • 테스트를 진행할 때 JUnit에서 실행자 외에 다른 실행자를 실행시킴
    • 여기서 SpringRunner라는 스프링 실행자를 사용
    • 스프링부트와 JUnit 사이에 연결자 역할을 함
  • @WebMvcTest(controllers = HelloController.class)

    • 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 헤더의 Status를 검증
    • 200, 404, 500 상태 검증
  • .andExpect(content().string(hello))

    • mvc.perform의 결과를 검증
    • 응답 본문의 내용을 검증
    • 컨트롤러에서 hello를 리턴하기 때문에 이 값이 맞는지 검증
  • @MockBean(JpaMetamodelMappingContext.class)

    • 사실 테스트 코드를 진행할 때 application 클래스에 @EnableJpaAuditing 해당 어노테이션이 있으면 오류가 난다.

Spring 컨테이너를 요구하는 테스트는 가장 기본이되는 --Application 클래스가 항상 로드되는데, @EnableJpaAuditing이 해당 클래스에 등록되어 있어 모든 테스트들이 항상 JPA 관련 Bean들을 필요로 하는 것이였다.

물론, @SprignBootTest를 사용할 때는 전체 컨텍스트를 로드하고 JPA를 포함한 모든 Bean을 주입받기 때문에 에러가 발생하지 않지만, @WebMvcTest같은 슬라이스 테스트는 JPA 관련 Bean들을 로드하지 않기 때문에 에러가 발생하였다.

해결방법
1) @MockBean(JpaMetamodelMappingContext.class) 추가
2) JpaAuditingConfiguration 클래스를 생성하여 @Configuration 어노테이션을 추가하여 분리

출처: https://jeongkyun-it.tistory.com/199

나는 여기서 1번 방법을 추가해서 test 클래스에 해당 어노테이션을 추가해줘서 에러를 해결했다.
사실 최상위 클래스인 Application에 @EnableJpaAuditing 코드를 지워주면 해결되지만 JPA에 대한 빈때문에 그냥 냅뒀다.

profile
주니어 개발자의 개발일지
post-custom-banner

0개의 댓글