본문 바로가기

study/Spring boot

스프링 부트 프로젝트 시작할 때, 몰랐던 것 - 테스트 코드, 패키지 구조 등등...

이동욱님의 책 "스프링 부트와 AWS로 혼자 구현하는 웹 서비스"를 보면서 기본적인 것들, 팁들을 많이 알았다. 이글의 출처이다.

 

테스트 코드는 중요하다. 대부분 단위 테스트를 필수조건으로 한다.
헷갈리면 안되는 것이 TDD와 단위 테스트는 다른 것이다.

 

TDD = 테스트가 주도하는 개발. (Test Driven Develepment)
1. 실패하는 테스트 코드를 먼저 작성하고 2. 테스트를 통과하는 프로덕션 코드를 짜고 3. 성공하는 프로덕션 코드를 리팩토링한다.

단위 테스트 = TDD의 첫 번째 단계인 "기능 단위의 테스트 코드"를 작성하는 것.

왜 테스트 코드를 작성해야 하나? 왜 중요한가?
* 개발단계 초기에 문제를 발견하도록 도와준다.
* 나중에 코드를 리팩토링하거나, 라이브러리가 업그레이드 되더라도 기존 기능이 잘 작동하는 지 확인할 수 있다.
* 기능에 대한 불확실성을 감소시킨다.
* 시스템에 대한 실제 문서를 제공한다. 단위 테스트 자체가 문서로 사용될 수 있다.(기능들을 검증하는 테스트니까)

 

-> 개인적인 경험으로 애플리케이션(톰캣)을 동작시키지 않고, 빠르게 기능을 확인할 수 있음.(애플리케이션을 작동시키는데 많은 시간이 든다.)

* 자동 검증이 가능하기 때문에 직접 눈으로 안봐도 된다.
* 새로운 기능이 추가됐을 때, 기존 기능이 잘 작동되는 지 확인할 수 있다.(기존 기능 작동 보장)

 

Junit(xUnit)으로 테스트 코드를 대게 작성한다.


일반적으로 패키지명은 웹 사이트 주소의 역순으로 한다.
만약 admin.shin.com 이라는 사이트가 있을 때, 패키지명은 com.shin.admin으로 한다.

 

@SpringBootApplication

  • 스프링 부트 프로젝트의 메인 클래스에는 @SpringBootApplication이라는 어노테이션을 붙인다.
  • 이 어노테이션으로 인해 스프링 부트의 자동 설정, 스프링 Bean 읽기와 생성을 모두 자동으로 설정된다.
  • 이 어노테이션이 있는 위치부터 설정을 읽어 가기 때문에 이 클래스는 항상 프로젝트의 최상단에 위치해야 한다.

메인 메소드에서  SpringApplication.run을 실행해서 내장 WAS를 실행한다.
-> 내장 was를 사용하면 서버에 톰캣을 설치할 필요가 없게 되고, 스프링 부트로 만들어진 jar파일로 실행하면 된다.

-> 꼭 내장 was를 사용할 필요는 없지만 스프링 부트에서는 내장 was 사용을 권장한다. => 언제 어디서나 같은 환경에서 스프링 부트를 배포할 수 있기 때문에


사용자 요청을 받는 컨트롤러 작성.

@RestController : json을 반환하는 컨트롤러로 만들어준다. 예전에는 각 메소드마다 @ResponseBody를 선언하던 것을 대체해준다.


@GetMapping("/hello") : get 요청을 받는 API 를 만들어준다. 예전에는 @RequestMapping(method = RequestMethod.GET) 으로 사용했던것이다.


테스트 코드를 작성할 때는 기본 소스 패키지를 그대로 생성하고 대상 클래스 이름 뒤에 Test를 붙여서 테스트 클래스를 생성하고 테스트 코드를 작성한다.

@ExtendWith(SpringExtension.class) : 테스트를 진행할 때, 공통적으로 사용할 기능을 적용할 수 있는 기능을 제공한다. 여기선 SpringExtension은 JUnit5의 Jupiter에서 스프링 테스트컨텍스트(TestContext)를 사용할 수 있도록 해준다.


@WebMvcTest(controllers = HelloController.class) : Web 테스트에 집중할 수 있게 하는 어노테이션
-> @Controller, @ControllerAdvice 등이 포함됨.

@Autowired : 스프링이 관리하는 빈을 주입받음

private MockMvc mvc; : 웹 API를 테스트할 때 사용함.
-> 스프링 MVC 테스트의 시작점.
-> 이 클래스로 GET, POST 등에 대한 API 테스트를 할 수 있다.

mvc.perform(get("/hello")) : MockMvc를 통해 /hello 주소로 get 요청을 한다.
체이닝이 지원돼 여러 검증 기능을 이어서 선언할 수 있다.

.andExpect(status().isOk()) : mvc.perform의 결과를 검증한다. HTTP Header의 Status를 검증한다.
-> 여기선 OK, 즉 200 인지 아닌지 검증한다.

.andExpect(content().string(hello)); : mvc.perform의 결과를 검증한다.응답 본문의 내용을 검증한다.
-> "hello"를 리턴했는지 검증한다.


또 다른 테스트 코드 작성.

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

isEqualTo : assertj의 동등 비교 메소드.
-> assertThat에 있는 값과 isEqualTo의 값을 비교해서 같을 때만 성공한다.
-> Junit, assertj 둘 다 assertThat 메소드를 갖고 있는데 assertj의 메소드는 추가 라이브러리가 필요하지 않아서 더 좋다.

 

.param("name", name) : API 테스트할 때 사용될 요청 파라미터 설정한다.

-> 값은 String만 돼서 모두 문자열로 바꿔 등록해야 한다.

.jsonPath("$.name", is(name))) : JSON 응답값을 필드별로 검증할 수 있는 메소드
-> $를 기준으로 필드명을 명시한다.

견고한 소프트웨어를 만들기 위해선 테스트 코드를 작성해야 한다. 
절대 수동으로 검증하고 테스트 코드를 작성하진 않는다. 테스트 코드 검증 후, 확인차 수동으로 검사한다.