작성
·
193
1
안녕하세요 강사님. 강의 정말 잘 듣고 실무에 적용해보려고 합니다. 강의 내용중 createPrinceTest_success 라고 하는 테스트 코드 예시에서 @Relaxed 로 모킹을 진행하고 오류가 발생해서 princeRepository.save()를 모킹하신다고 하셨는데, 그 이유가 어떤 이유인지 궁금합니다.
CreatePrince.Request 객체를 만들고 princeMakerService.createPrince(request)를 호출하여 내부의 princeRepository.save()를 통해 저장되는 것을 테스트 하는데 외부에서 princeRepository.save()를 다시 모킹을 진행하고 랜덤 값으로 Prince 객체를 리턴 받는것이 조금 이해가 되지 않아서 질문드립니다.
질 좋은 강의 너무 감사드립니다. 답변 주시면 감사하겠습니다!
답변 1
0
안녕하세요. 최진호님! 좋은 질문 감사드립니다.
(우선 제 강의를 듣고 실무에 적용해보려 하신다니 강의의 목적을 이룬 것 같아 뿌듯합니다😄 )
일단 말씀주신 부분의 강의를 제가 다시 주의깊게 들어보니 빠르게 진행되면서 설명이 부족한 부분이 있었네요ㅠㅠ
@RelaxedMockK로 모킹을 하는 것은 중요한 기능을 모킹하고 덜 중요하고 반복적인 부분에서의 모킹은 덜 하기 위함입니다. 그래서 완화된(Relaxed) 모킹을 사용하는 경우 기본적인 타입(Int, Long, String 등)과 널러블한 응답을 하는 함수들은 각 타입의 기본 값인 0, "", null 등을 반환합니다.
하지만 RelaxedMockK 모킹이 잘 안되는 케이스가 있는데 바로 Generic Type입니다. 이 경우에는 해당 타입을 정확히 알 수 없어서 기본값을 찾지 못하고 완화된 모킹이 설정되지 않기 때문에 직접 모킹을 진행해줘야 합니다. MockK 문서의 해당항목에서도 "Note: relaxed mocking is working badly with generic return types. A class cast exception is usually thrown in this case. Opt for stubbing manually in the case of a generic return type." 라고 언급을 하고 있습니다.
그리고 JpaRepository의 Inteface를 살펴보시면 아래와 같이 save 메서드가 S라는 Generic Type을 사용하고(파라미터와 응답 값으로) 있는 것을 알 수 있습니다. 따라서 이 함수의 동작은 완화된 모킹으로 동작하지 않아서 직접 모킹을 수행해줘야 했습니다.
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity);
관련 MockK github issue도 있으니 참고해보세요 😀 : https://github.com/mockk/mockk/issues/321
또, JpaRepository로 save를 수행하면 결과로 영속화가 완료된 Entity를 응답하게 되는데 테스트하는 코드에서는 save의 응답 값을 따로 사용하지 않습니다. 따라서 응답하는 값은 어떤 값이 나와도 무방하고 그냥 Prince Entity 타입이기만 하면 되는 상황이었습니다^^;;
그래서 랜덤한 값으로 빠르게 생성하는 작업을 보여드리려고 Fill Class도 소개하면서 겸사겸사 설명드리다보니 생략이 많이 된 것 같습니다.
설명에서 놓친 부분에 대한 좋은 질문 주셔서 감사드립니다. 🙇♂
실무에서 재미있게 활용해보세요~^^
(참고로 올해 하반기에 '코틀린 함수형 프로그래밍 입문(가칭)'도 출시 예정입니다. 많은 기대 부탁드려요~!)
세열님 상세하게 설명 해주셔서 이해가 정말 잘 되었습니다!
코틀린 테스트 코드를 어떻게 작성하는 것이 좋을까 강의를 찾아보다 듣게 되었는데 너무 만족스러운 강의였습니다. 덕분에 테스트 코드를 작성하는것이 재미있어졌네요
앞으로도 질 좋은 강의 잘 부탁드리면서 응원하겠습니다 감사합니다!!🙇♂