현재 진행하고 있는 사이드 프로젝트(이하 블루밍)에서 골에 참여한 참여자 리스트를 수정하는 로직을 구현했다. 기존 참여자는 수정할 수 없되, 신규 참여자는 추가할 수 있도록 로직을 구현하고 도메인 단위 테스트를 수행하던 중 문제가 발생했다.
골 도메인 테스트에서 골 참여자 목록을 2명에서 3명으로 수정했는데도 불구하고 계속해서 result
가 2명으로 떴다. 처음엔 수정 로직의 문제인가? 했는데 복잡한 로직도 아니고 수정 요청받은 참여자 리스트에 있는 사용자들이 기존 참여자 리스트에 포함되어 있는지 contains()
메서드로 검증했을 뿐이었다. 결과적으로 contains()
메서드를 사용해 true/false 값을 받아 검증하던 if문을 추가된 참여자도 들어가지 못하는 문제를 발견했다. (이거 알아내겠다고 코드 한줄한줄마다 출력값 다 받아서 비교해봤다...) 그런데 이해가 되지 않았다. 기존 참여자 리스트에 없는 사용자면, 당연히 contains()
메서드에서 false
가 반환이 되어야하는데 왜 true
가 반환이 된건지 이해를 할 수 없었다. 내 경험치로는 해결할 수 없는 문제인 것 같다 싶어서 결국 제이미님께 도움을 요청했다.
문제는 사용자 엔티티에 설정해주었던 EqualsHashCode
설정 때문이었다. EqualsHashCode
설정으로 id
를 넣어주었는데, 무슨 뜻이냐 하면 엔티티가 동일한지 비교 검증을 할 때 모든 필드를 다 비교하는 것이 아닌 id
값으로 비교하겠다는 의미이다.
RepositoryTest
또는 ServiceTest
에서는 직접 EntityManager
를 사용해 (혹은 JpaRepository
를 사용해) 값을 메모리에 save
해주니 당연히 id
값이 존재했다. (id 값을 설정해줄 때 @GeneratedValue(strategy = GenerationType.IDENTITY)
를 사용해 자동 설정해주었다.)
그러나 도메인 테스트는 메모리에 save
해주지 않고 도메인을 Build
해 사용하는 것이다 보니 모든 사용자 객체의 id
값이 null
이어서 기존의 사용자들과 신규 추가된 사용자가 동일한 사용자로 인식된 것이었다..!!
의심을 해보긴 했으나 해결방안이 떠오르지 않아 외면하고 있었다... id
값 넣어주겠다고 프로덕션 코드를 건드는 것은... 용납할 수 없었기에 마땅한 해결책을 찾지 못했던 것이다. 그러던 중 제이미님이 제안해주신 해결방법은
테스트 코드에서 값을 설정해주고자 하는 변수에 임의로 내가 값을 설정해줄 수 있다.
아래는 사용 예시이다.
ReflectionTestUtils.setField(유효한_사용자, "id", 1);
ReflectionTestUtils.setField(유효한_사용자2, "id", 2);
ReflectionTestUtils.setField(유효한_사용자3, "id", 3);
프로젝트에 사용한 실제 코드는 아닙니다.
이렇게 자동 설정해주어야 하는 필드값을 단위테스트 환경에서 직접 설정해주어야할 때, ReflectionTestUtils
를 사용하면 불필요하게 프로덕션 코드에 설정해주는 메서드를 선언해줄 필요없이 테스트를 진행할 수 있을 것 같다.