스프링/백엔드

스프링 부트의 테스트 코드(부제 : JUnit), 책: 스프링 부트와 AWS로 혼자 구현하는 웹 서비스

지팡구 2022. 2. 10. 21:44

결국 테스트 코드를 작성하는 이유는, 기능이 잘 동작하는지 확인을 하기 위함이다. 

테스트 코드는 내가 작성한 로직이나 기능들을 테스트 코드를 통해 잘 동작하는지 확인해보는 것이다.

 

테스트 코드 작성 전 개발 방식은 보통

 

1. 코드의 작성

2. 프로그램 실행

3. 테스트 도구를 통해 HTTP 요청 (Postman)

= 브라우저를 통해 서버에 접속하고 테스트 대상 메소드를 동작시키는 요청

4. 요청 결과를 System.out.println()을 통해 눈으로 확인.

5. 결과가 이상하면 프로그램 실행을 중지하고 코드를 수정

 

이런 방식으로 많이 진행 되었는데, 테스트 코드를 작성하게 되면,

 

1. 코드를 작성

2. 테스트 코드의 작성 후 실행 

3. 결과에 따른 동작(코드를 수정한다, 정상 작동하니 다음 로직을 개발한다 등등..)

 

과정이 한 눈에 봐도 줄어드는 것을 확인할 수 있다.

 

그래서 테스트 코드를 작성함으로써 계발 초기에 문제를 발견할 수 있다.

또한 앞서 언급한 기능의 동작을 확인할 수 있다.

이로 인해 기능에 대한 불확실성을 감소시킬 수 있다.

 

테스트 코드 작성시 많은 곳에서는 given/ when/ then을 사용하는 것을 확인할 수 있다.

이를 사용함으로서 코드의 가독성이 향상되는데, given은(값의 전달), when은(동작),then은(결과)를 의미한다.

 

테스트 코드의 가독성이 중요한 이유는 테스트 코드가 문서로써의 역할을 할 수 있기에, 테스트 코드를 확인함으로써, 해당 메소드를 작성한 개발자의 의도를 살짝 알아볼 수 있다. 


 

각 언어별 테스트 코드의 작성을 도와주는 프레임워크들이 있는데, Java에서는 JUnit이 있다. 

(현재 JUnit5까지 나왔지만, 대부분 4를 사용하고 있다고 한다?..) 아마 이제는 5를 사용하지 않을까?....

 

현재 내가 공부하고 있는 책인 '스프링 부트와 AWS로 혼자 구현하는 웹서비스' 라는 책에서 

@RunWith라는 어노테이션을 사용했다.  이 어노테이션은 JUnit4에서 사용이 가능한데, JUnit5가 되면서 @ExtendWith로 변경되었다.  그래서 어노테이션은 물론 import 패키지 또한 달라진다는 점을 알아야 한다. 

 

@RunWith라는 어노테이션은 테스트를 진행할 때 JUnit에 내장된 실행자 외 다른 실행자를 실행시키는데, 해당 책에서는 SpringRunner라는 스프링 실행자를 사용한다. (즉, 스프링 부트 테스트와 JUnit 사이에 연결자 역할을 함.)

JUnit4

앞서 말했던 것처럼, RunWith를 사용하지 않기에, 이 코드인 SpringRunner도 바꿔줘야 하는데,  이 코드 대신, @ExtendWith(SpringExtension.class)라는 코드를 사용한다.

JUnit5

여기사 내가 궁금했던 점은 과거 스프링부트를 배우는 도중 저런 어노테이션을 사용했나? 라는 의문이 들었고, 확인해본 결과 @SpringBootTest라는 어노테이션을 사용했다.  

 

그럼 왜 이 책에서는 @SpringBootTest를 사용하지 않고 @RunWith를 사용하는 것이지? 라는 궁금증이 생겼다.

 

찾아본 결과 우선 @SpringBootTest 어노테이션이 @Extendwith(SpringExtension.class)를 가지고 있다는 점을 알았다. 

 

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@ExtendWith({SpringExtension.class})
public @interface SpringBootTest {
    @AliasFor("properties")
    String[] value() default {};
...
}

해당 어노테이션의 소스 코드의 일부인데 확인해보면 이미 메타 어노테이션으로 사용됐고, 코드를 가지고 있음을 확인할 수 있다. 

 

또한 @Extendwith(SpringExtension.class)와 SpringBootTest 어노테이션을 같이 사용할 수 있음을 알게되었다.

@SpringbootTest는 통합 테스트를 진행할 때 사용하는 어노테이션인데, 통합 테스트는 다른 모듈이 그룹으로 결합 될 때 잘 동작하는지 확인하는 것이다.  

 

통합 테스트를 찾으면서 단위 테스트에 대해 찾게 되었는데, 단위 테스트는 코드가 제대로 동작하는지 확인하기 위해 애플리케이션의 개별 모듈을 독립적으로 테스트 하는 것을 말한다. 

 

그럼 결국 이 부분은 전체를 테스트 하기 위함이 아닌 일부분을 테스트 하기 위함이라 통합 테스트 어노테이션이 아닌 단위 테스트 어노테이션을 사용한 것이라고 생각할 수 있다.

 

이렇게 생각한 이유는 단위 테스트의 정의와 책에서 사용되는 테스트 소스 코드 중에 @WebMvcTest라는 어노테이션을 사용했는데, 이 어노테이션이 단위 테스트를 위해 사용함을 알게되었다.

 

(그럼 여기서 @WebMvcTest는 뭐지?)

 

앞서 스프링에는 여러 테스트 어노테이션이 있다고 했는데, 그 중 WebMvcTest는 WEB에 집중할 수 있는 어노테이션이다. (웹이서 테스트하기 함든 컨트롤러를 테스트하는 데 적합하다.)

 

이 어노테이션을 통해 웹상에서 요청과 응답에 대해 테스트 할 수 있으며 SpringBootTest보다 가볍게 테스트 할 수 있다.

 

선언을 통해 @Controller, @ControllerAdvice 등 몇 가지 내용만 스캔하도록 제한하고 있으며, @Service, @Component 등은 사용할 수 없다.

 

 

Spring 공식문서

< 참고 >

https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing

 

Core Features

Spring Boot lets you externalize your configuration so that you can work with the same application code in different environments. You can use a variety of external configuration sources, include Java properties files, YAML files, environment variables, an

docs.spring.io

 

'스프링 > 백엔드' 카테고리의 다른 글

Repository와 Service  (0) 2022.06.12
로깅 간단히 알아보기  (0) 2022.05.18
REST API 기초와 사용법 (2022.12.08 추가)  (0) 2022.03.28
InteliJ-Spring boot-dependencies  (0) 2022.03.09
Compile과 implementation의 차이점  (0) 2022.01.30