일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- mapstruct
- backend
- ExceptionResolver
- RequestBody
- ObjectMapper
- FCM
- proxyFactory
- 자바
- Service 계층 테스트
- 소프티어
- 공룡책
- Junit 5
- Test
- JPQL
- Test Doulbe
- enumSet
- softeer
- OS
- 인프콘2023
- 일상
- Java
- JPA
- modelmapper
- Spring
- db
- Coputer Science
- MySQL
- 테크쇼
- Server
- Test code
- Today
- Total
공부내용공유
Junit 5 Service,Mapstruct, ModelMapper Unit Test (단위 테스트) 본문
서론
현재 진행중인 프로젝트에서 잘만 돌아가던 API 가 안된다고 프론트 팀원분에게 연락이 왔고 나는 로그를 보고 오류를 확인을 했는데 다름이 아닌 다른 파트를 맡은 친구가 자신의 파트에서 기능 일부분을 수정했고 자신의 파트만 되는지 시행해 보고 PR 을 넣었던 것이다.
나도 그냥 기능을 수정했나 보다라고 간과하고 PR을 받았고 그 결과 내가 만들었던 API가 영향을 받아 오류가 났던것이다.
이를 경험하고 Test Code 의 중요성을 깨닫고 PR 을 넣을때는 적어도 Unit Test 는 모든 파트에서 돌려보고 넣는게 맞겠구나 라는 생각이 들어 Test Code 를 작성하게 되었다.
본론
Service 계층에서의 Test Code 를 먼저 작성하였다.
이 글에서는 내가 진행한 프로젝트에서 Junit 5 를 통해 어떤식으로 테스팅을 했는지 정리할것이다.
여러 레퍼런스를 찾아보면서 작성을 하였지만 부족한 부분이 많고 추후 책이나 강의등을 통해 제대로 공부하고 다시 리팩토링을 할 예정이다.
서비스 계층은 Controller 계층과 Repository 계층과 연결되어져 있고 그중 Repository 계층에는 의존을 하면서 Repository의 메서드를 사용한다.
그리고 이번 프로젝트에서 나는 mapping을 위해 MapStruct 와 ModelMapper 를 서비스 계층에서 사용하였다.
여기서 이제 Test Double 을 사용하여 Mock 할것과 Spy 할것 등을 정하고 테스트를 만들어야 한다.
- Repository - Mock
- modelMapper - Mock
- mapStruct - Spy
여기서 왜model mapper 는 mock을 하고 maprStruct는 spy를 한 이유는
mapStruct의 경우는 각 mapper 마다 내가 어떻게 로직을 설정하냐에 따라 결과가 달라지기 때문이다.
MapStrcut Test
예를들면 Lecture 와 User 를 사용해서 특정 DTO를 만들때 mapStruct 를 사용한다 가정하자.
이때 두 객체에 같은 이름을 가진 level 이라는 필드가 있다면 내가 어떤 DTO를 만드냐에 따라 user 의 level 필드가 사용되어야 할때가 있고 Lecture의 level 필드가 사용되어야 할 때가 있다.
이러한 경우에 내가 mapStruct interface를 설정을 알맞게 해야 원하는 DTO가 만들어지고 이는 서비스 계층에서 굉장히 중요한 일중 하나라고 생각이 들어 mapStruct는 spy 로 받아 직접 mapStruct 만 테스트를 하였다.
이 경우는 굉장히 단순한 경우이지만 추후 복잡한 mapStruct 테스트를 만들게 되면 따로 정리 할예정이다.
그 이후 서비스의 한 메서드인 createLectureContent를 테스트를 하였다.
위 테스트에서 이미 mapStruct의 테스트는 진행했으므로 여기서는 given 을 통해 작동하지 않게 하였다.
ModelMapper
위 사진에서 보면modelmapper 는 Mock으로 설정을 하였다.
mapStruct는 위 설명과 같이 다양한 설정과 다양한 결과가 나오기 때문에 직접 Test 를 작성했지만
ModelMapper의 경우는 한 설정으로 계속 같은 방식으로 사용하기 때문에 테스트를 할 필요가 없다 생각이 들어 Mock으로 작성해 주었다.
그 후 doNothing 을 통해 행동을 제한해 주었다. (Stubber 방식 사용)
원래는 일관성을 위해 onGoingStubbing 을 사용하고 싶었으나 ModelMapper.map() 은 return 타입이 void였고 이는 onGoingStubbing에서 받지 않아서 Stubber 방식을 사용하였다.
Stubber란? OnGoingStubbing 이란?
BeforeAll, BeforeEach
테스트 진행을 위해 필요한 객체가 있을 수 있다.
BeforeAll 이나 BeforeEach 어노테이션을 사용하여 각 테스트를 위해 객체를 준비할 수 있는데
나는 필요할때만 객체를 사용하고 싶어서 메서드로 만들고 필요할때 사용하는 식으로 테스트를 작성하였다.
결론
처음 Service 계층 테스트 코드를 작성하면서 많은 고민을 하고 자료를 찾아 보았다.
- 어느정도의 세부적인 단위로 나눠서 테스트를 해야하는지
- 외부 유틸리티 기능들은 Spy를 활용할지 Mock을 활용할지
- Exception은 어떤 방식으로 테스트를 해야하는지
추후 책이나 강의를 통해 좀 더 잘 공부하고 테스트 코드를 리팩토리 할 예정이다.
'Spring > Spring' 카테고리의 다른 글
FCM 기능 구현 및 리팩토링을 하면서의 고민들 (0) | 2023.09.08 |
---|---|
Spring Proxy Factory 뜯어보기 (0) | 2023.09.05 |
Test Code H2 DB 사용시 주의사항 (0) | 2023.07.28 |
Spring ModelMapper, MapStruct 적용에 관하여 (2) | 2023.06.01 |
Test Double이란? (0) | 2023.05.20 |