본문 바로가기

Junit/Mockito

[Mockito] mockito에서 when 구문 사용시 주의점


새로 이직한 회사에서는 단위 테스트 작성시 Mockito를 사용한다.

처음부터 사용한건 아니었던것 같고.. 최근에 Mockito로 변환하거나 요즘 작성하는 테스트케이스를 Mockito로 작성하는 중인듯하다.


간단하게 개발을 진행 할 일이 생겨서 DAO, Service 클래스를 개발하면서 

테스트케이스를 만들었다. DAO는.. 단순 CRUD이긴 하지만.. 일단은 그냥 개발DB에 바로 붙어서 

테스트 케이스가 돌아가도록 만들어놨다. 문제는 이부분이 아니라.. Service 클래스의 테스트 케이스였는데..

Mockito를 읽기만하고 써본적이 없어서.. 헤매고 있는 와중에 현기형(eclipse4j)이 옆에 와서 잠깐 짝코딩을 하게 되었다.



Service 클래스의 테스트케이스를 작성하려면 일단 Service 클래스에 Autowired로 엮여있는 DAO를 통해 데이터를 가지고 와야 하는데, 이 부분에서 DAO가 실제로 DB로 접근하여 데이터를 가져오지 않도록 Mockito의 when을 사용하는 것이었다.




실제 테스트클래스는 맨 아래의 코드인데..

소스를 보면 Service 클래스에서 Param 객체를 생성하여 DAO에 넘겨주면서 select를 실행하게 되어있었다.

Service를 사용하게 될 다른 팀의 개발자들에게는 굳이 Param을 노출 할 필요가 없어서 위와 같이 만들어 놓았었고

아무튼 Mockito를 아래와 같이 사용을 하도록 해놨었다.


when(dao.select(new Param())).thenReturn(new Result());
service.select();


그런데 테스트케이스를 실행하면 Result의 객체가 생성이 안되는 것이었다.


분명히 메서드도 맞는데... 


현기형과 둘이 앉아서 보면서.. "음.. 이상하다?" 하며 있다가 형이 "파라메터를 없는 메서드로 한번 테스트해보자"라고 해서 DAO에 파라메터를 받지 않는 메서드를 추가하고, 그 메서드를 사용하여 when thenReturn 구문을 다시 작성해보았다.


when(dao.select()).thenReturn(new Result());

service.select();


그랬더니 이건 정상적으로 실행이된다?
dao.select()가 실행되는 것을 잡아낼때 Param의 객체가 어떤 방해요소가 되는 것 같은 생각이 들어서 내가 "형 Param에 equals를 일단 true만 리턴하게 해서 다시 원래대로 해보죠" 라고 이야기하여 테스트를 해보니 역시 성공.

Mockito의 소스를 열어보려다가 시간이 없어서 그러지는 못 했는데 when 구문에서 파라메터로 넘긴 Param 객체와 실제로 Service 클래스 안에서 생성된 Param 객체가 달라서 (Object의 equals 비교) 같은 메서드 실행을 인지하지 못 하는 것 같았다.

마침 회사 내부적으로 equals, toString, hashCode를 클래스별로 알맞게 자동으로 구현해주는 상위 도메인 클래스가 이미 있어서 그놈을 사용하여 해결하였다.

금요일에는 잊지말고 Mockito가 when, thenReturn을 실행하는 방식을 한번 분석해봐야겠다.

------ 추가
ologist님께서 댓글을 달아주신 것을 보고 글에서 얘기하고자 하는 내용이 다소 애매한듯하여.. 다시 정리하자면..
결국 Mockito에서 when/thenReturn을 사용할때 메서드의 파라메터로 넘어오는 클래스까지 equals를 사용하여 비교하는듯 하다. (요 부분을 한번 소스 분석을 통해 확인해보고 싶은거구요..)

실수를 했던 부분은 mockito의 when/thenReturn을 사용하기 위해서 메서드 실행을 감지할때, 메서드의 파라메터로 넘어가는 객체까지 비교가 될거라고 생각하지 못 한거였고... 그래서 주의할점은 .. 꼭 Mockito 사용을 위해서가 아니고 Effective 자바등에서도 강조하듯이 클래스의 equals/hashCode등은 꼭 알맞게 구현해야하겠다.. 라는 것.. ^^