Spring Boot 단위 테스트에 대해 알아보자.
이 기능을 알기 전에는 아마도.. 직접 웹을 띄워 테스트를 하거나
API tester를 이용했던 것 같다. tomcat이 올라갈 때 까지 기다리고,, 에러나면 어디서 났는지 로그 보고,,찾고,,
인류발전 만만세,,😆
❓ 단위테스트란?
TDD의 첫 번째 단계인 기능 단위의 테스트 코드를 작성하는 것을 말한다. (필수는 아님 => 그러나 지향해야한다.)
※ TDD?
테스트 주도 개발이다. 테스트 코드를 먼저 작성한 후 개발을 한다. 순서는 레드 그린 사이클을 따른다.
레드 그린 싸이클
1. RED: 항상 실패하는 테스트를 먼저 작성
2. GREEN: 테스트가 통과하는 프로덕션 코드를 작성
3. REFACTOR: 테스트가 통과하면 프로덕션 코드를 리팩토링
❓ 왜 지향해야 할까?
개발 단계 초기에 문제를 발견할 수 있다. 앞서 얘기한 것 처럼 이미 전체를 구현하고 서버를 실행시켰을 때 기능 중에 하나가 오류가 발생한 경우 찾아내기가 더 까다로울 수 있다.
각 기능에 대한 단위테스트가 있다면 사전에 검증하여 오류를 잡아낼 수 있다.
Spring Boot에서는 org.springframework.boot:spring-boot-start-test를 지원한다.
여기서 간단히 테스트에 필요한 라이브러리들을 제공한다.
✅ 사용해보기
1) build.gradle에 test 추가하기
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.apache.pdfbox:pdfbox:2.0.1'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
}
아, 참.
이 프로젝트를 구현할 때 처음 설정했던 프로젝트 이름을 이후 작업 중에 변경하였었다.
그랬더니 빌드가 안되고 오류가 떠서 자바 버전이 문제인지 혹시 옵션 설정이 뭐가 잘못되었는지 한 30분 고민했던 것 같은데 setting.gradle에 rootProject 이름 안바꿈 ^^ 혹시 나중에도 이런 일이 생길까봐 적어놓는다.
2) 테스트를 위한 Controller 만들기
@RestController
public class FirstController {
@PostMapping("/first")
public String hello(UserInfo user) throws Exception {
return user.getId() + "의 테스트";
}
}
POST HTTP Method로 요청을 받는 API를 작성하고 이 클래스를 JSON으로 반환하는 컨트롤러로 만들기 위해 @RestController 어노테이션을 추가한다.
3) DTO 추가
public class UserInfo {
private String id;
public UserInfo() {
}
public UserInfo(String id) {
this.id = id;
}
}
4) 테스트 코드 작성하기
@WebMvcTest(controllers = FirstController.class)
class FirstControllerTest {
@Autowired
private MockMvc mvc;
@Autowired
private ObjectMapper objectMapper;
@Test
public void test() throws Exception {
String content = objectMapper.writeValueAsString(new UserInfo("sylim"));
mvc.perform(post("/first")
.content(content)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(print());
}
}
✔ 어노테이션과 기능에 대해 알아보자.
버전 | Spring MVC 테스트 | 단위 테스트(Mockito) | Spring 통합테스트 |
2.2 이전 | @RunWith(MockitoJUnitRunner.class) | @RunWith(MockitoJUnitRunner.class) | @RunWith(SpringRunner.class) @SpringBootTest |
2.2 이후 | @WebMvcTest | @ExtendWith(MockitoExtension.class) | @SpringBootTest |
- @Autowired : Spring이 관리하는 Bean을 주입받는다.
- MockMvc : 웹 API를 테스트할 때 사용한다. (HTTP GET, POST 등에 대한 API 테스트 가능)
- content : 응답에 대한 정보를 검증해준다.
- perform(post("/first")) : MockMvc를 통해 HTTP 요청을 한다.
- andExpect(status().isOk()) : perform의 결과를 검증한다.
* 상태코드(status())
- isOk() : 200
- isNotFound() : 404
- isMethodNotAllowed(): 405
- isInternalServerError(): 500
- is(int status): status 상태 코드
- andDo(print()) : 요청/응답 전체 메세지를 확인할 수 있다.
5) 실행하기
JUnit테스트로 실행하면 성공한 화면과 전체 메세지를 확인할 수 있다.
👁🗨 마치며
어떻게 보면 번잡스럽기도, 어떻게 보면 편하기도 한 기능이다.
어떻게 활용하느냐는 개발자의 몫이니 열심히 사용해보도록 하자. 기능 하나 하나 테스트를 해가는 것이 전체 프로젝트의 오류를 줄일 수 있을 것이다.
'개발 Note > SPRING' 카테고리의 다른 글
[SPRING] Spring AOP (0) | 2022.06.14 |
---|---|
[SPRING] Spring boot - 외부 jar 추가 후 테스트하기 (0) | 2022.04.23 |
[SPRING] Spring Security (0) | 2022.03.26 |