서비스 레이어 단위 테스트를 작성하고 있었습니다!
작성한 테스트 코드는 다음과 같습니다.
isEqualTo()
를 사용한 테스트 코드@Test
@DisplayName("[회원 세부 정보 조회] 사용자는 자신의 정보를 조회할 수 있어야 한다.")
public void getMemberInfo() throws Exception {
// given
String id = "mungmnb777";
Member expectedMember = MockEntityFactory.createMember();
Mockito.when(memberRepository.findById(id)).thenReturn(Optional.of(expectedMember));
// when
MemberInfoResponseDto actual = memberService.getMemberInfo(id);
MemberInfoResponseDto expected = new MemberInfoResponseDto();
expected.convertFromEntity(expectedMember);
// then
assertThat(actual).isInstanceOf(MemberInfoResponseDto.class);
assertThat(actual).isEqualTo(expected);
}
isEqualTo()
메서드는 값 비교 메서드이지만, 객체 비교를 할 때에는 참조 주소로 비교합니다.
그래서 Reflection을 이용해서 값 비교를 해봤어요.
Reflection
을 활용한 테스트 코드@Test
@DisplayName("[회원 세부 정보 조회] 사용자는 자신의 정보를 조회할 수 있어야 한다.")
public void getMemberInfo() throws Exception {
// given
String id = "mungmnb777";
Member expectedMember = MockEntityFactory.createMember();
Mockito.when(memberRepository.findById(id)).thenReturn(Optional.of(expectedMember));
// when
MemberInfoResponseDto actual = memberService.getMemberInfo(id);
MemberInfoResponseDto expected = new MemberInfoResponseDto();
expected.convertFromEntity(expectedMember);
// then
assertThat(actual).isInstanceOf(MemberInfoResponseDto.class);
Method[] methods = MemberInfoResponseDto.class.getMethods();
List<Method> filteredMethods = Arrays.stream(methods)
.filter(m -> m.getName().contains("get"))
.filter(m -> !m.getName().equals("getClass"))
.collect(Collectors.toList());
for (Method method : filteredMethods) {
assertThat(method.invoke(actual)).isEqualTo(method.invoke(expected));
}
}
그런데 이 때는 MemberInfoResponseDto 내부에서 참조하고 있는 AvatarResponseDto의 동일성 비교를 실패해서 테스트가 깨졌어요 😢
DTO에 equals()
와 hashcode()
를 재정의하면 쉽게 해결할 수 있는 문제였지만, 다른 방법으로 해결을 해보고 싶었어요.
그래서 인터넷에서 assertj
가 제공해주는 메서드가 있는지 한번 찾아봤어요.
결론적으로 usingRecursiveComparison()
이라는 메서드를 이용하면 VO가 아닌 것들을 대상으로 내부 값 비교를 할 수 있다고 해요! 원리는 내부적으로 모든 값을 재귀적으로 돌면서 값을 비교한다고 하네요.
usingRecursiveComparision()
을 사용한 테스트 코드@Test
@DisplayName("[회원 세부 정보 조회] 사용자는 자신의 정보를 조회할 수 있어야 한다.")
public void getMemberInfo() throws Exception {
// given
String id = "mungmnb777";
Member expectedMember = MockEntityFactory.createMember();
Mockito.when(memberRepository.findById(id)).thenReturn(Optional.of(expectedMember));
// when
MemberInfoResponseDto actual = memberService.getMemberInfo(id);
MemberInfoResponseDto expected = new MemberInfoResponseDto();
expected.convertFromEntity(expectedMember);
// then
assertThat(actual).isInstanceOf(MemberInfoResponseDto.class);
assertThat(actual).usingRecursiveComparison().isEqualTo(expected);
}
정상적으로 테스트를 통과했습니다!