Service의 테스트코드를 작성하다가 아래의 문제를 마주쳤다.
즉 User라는 클래스에 id가 null인 경우다.
@BeforeEach
void set_up(){
// given
accessToken = "test_access_token";
userId = 1L;
mockUser = User.builder()
.email("test@test.com")
.profileImage("test")
.nickname("test")
.isOnline(true)
.type("kakao").build();
테스트 코드에서 User라는 mock객체를 만들 때 id값은 따로 넣어주지 않는다.(Auto Increment)
또한 service에서 테스트를 진행하기에 따로 save를 해주지도 않았었는데 이 부분이 문제라고 생각했다.
그러면 내가 생각했던 해결 방법은 2가지이다.
1. save를 진행한 후 TestEntityManager로 캐시 삭제
2. Builder에 id 삽입
1번의 경우 Service 테스트 목적에 맞지 않는다고 판단했다.
서비스 테스트를 진행할 때 repository는 결국 우리의 예상대로 결과가 나와야하기에 나는 Mockito를 이용해서 예측 결과값을 넣어주고 있다.(즉 A를 넣으면 B가 나오도록 미리 설정)
2번의 경우 실제 서비스에서는 id를 따로 넣어주지 않는데, 굳이 테스트를 위해서 빌더에 id를 넣을 필요는 없다고 판단했다.
여기서 나왔던 개념은 Reflection이었다.
리플렉션
자바에서 구체적인 클래스 타입을 모르더라도 해당 클래스의 변수, 타입, 메서드에 접근이 가능하게 해준다.
리플렉션을 사용해서 우리가 만든 유저의 id 필드에 접근해서 값을 집어넣어주면 된다.
@BeforeEach
void set_up() throws NoSuchFieldException, IllegalAccessException {
// given
accessToken = "test_access_token";
userId = 1L;
mockUser = User.builder()
.email("test@test.com")
.profileImage("test")
.nickname("test")
.isOnline(true)
.type("kakao").build();
Field id = mockUser.getClass().getDeclaredField("id");
id.setAccessible(true);
id.set(mockUser, userId);
그래서 아래 3개의 코드를 추가했다.
mockUser.getClass()를 통해서 해당 유저의 클래스를 가져온다.
getDeclaredField("id"); 를 통해서 클래스의 id 필드에 접근한다.(여기서 리플렉션이 사용되었다. 구체적인 클래스를 몰라도 필드에 접근할 수 있도록 한 것)
접근이 가능하도록 true로 만든 다음에 해당 id에 값을 변경해주었다.
이렇게 하면 db의 오토인크리먼트를 이용해 id를 집어넣어준 것과 같은 결과가 나오게 된다.
사실 리플렉션의 개념이 모호했는데 이렇게 테스트 코드를 직접 짜면서 사용해보니 어떻게 사용하는지 이해가 된다.
'프로젝트 > 씈크럼 프로젝트' 카테고리의 다른 글
쿼리 메서드 사용으로 인한 성능 개선 (0) | 2024.02.09 |
---|---|
조작된 토큰으로 SignatureException 발생 예외 처리 (0) | 2024.02.02 |
Swagger를 배포한 상태로 사용해보기 (0) | 2024.02.01 |
현재 스프링부트 프로젝트에 유효성 검사 진행하기 (1) | 2024.01.31 |