Mockito – How about some stubbing?

참조 : http://mockito.googlecode.com/svn/branches/1.4/javadoc/org/mockito/Mockito.html

 //인터페이스가 아니라, 클래스의 mock 객체도 생성할 수 있다.
//easymock 보다 편하군요. easymcok은 extention 라이브러리를 설치해야 사용할 수 있죠.
 LinkedList mockedList = mock(LinkedList.class);
 
 //Stubbing
 stub(mockedList.get(0)).toReturn(“first”);
 stub(mockedList.get(1)).toThrow(new RuntimeException());
 
 //”first”를 출력할 것이고..
 System.out.println(mockedList.get(0));
 
 //RuntimeException을 던질 것이고..
 System.out.println(mockedList.get(1));
 
 //get(999)는 stubbing 하지 않았으니까 “null”을 출력할 겁니다.
 System.out.println(mockedList.get(999));
 
 //Stubbing 한 호출들은 암묵적으로 검증을 합니다. 여러분이 원하는 예외적인 흐름 상 해야만 한다면 해도 상관없습니다.
 //명시적으로 스텁 호출을 검증하는게 가능하긴 한데, 대부분의 경우 그럴필요까진 없습니다.
 verify(mockedList).get(0);

  • 기본적으로, 반환 값이 있는 모든 메소드들은, mock은 null을 반환하거나, 비어있는 콜렉션 또는 적절한 primitive 값을 반환합니다.(e.g: 0, false, … for int/Integer, boolean/Boolean, …).
  • 스텁 작업은 오버라이딩 할 수 있습니다. 예를 들어, 스텁으로 fixture를 만들어 둘텐데 그걸 테스트 메소드내에서 재정의할 수 있습니다.
  • 한 번 스텁을 만들어 두면 mocking한 메소드는 몇 번을 호출하든 상관없이 항상 스텁 값을 반환합니다.
  • 같은 메소드를 여러번 스텁 했을 때는 마지막에 스텁한 녀석이 더 중요합니다.
  • 명시적으로 스텁 호출을 검증하는 것이 가능하긴 한데, 대부분의 경우 불필요 합니다. 스텁 호출은 암묵적으로 검증을 합니다. 여러분이 작성한 코드의 실행 흐름에 따라 알아서 해줄 겁니다.

EasyMock Code

    @Test
    public void get() {
        int id = 1;
        Member member = new Member();
        member.setId(id);
        expect(mockDao.get(id)).andReturn(member);
       
        replay(mockDao);
       
        assertEquals(member, service.get(id));
       
        verify(mockDao);
    }

Mockito Code

    @Test
    public void get() {
        int id = 1;
        Member member = new Member();
        member.setId(id);

        stub(mockDao.get(id)).toReturn(member);
       
        assertThat(service.get(id), sameInstance(member));
    }

흠 오늘은 service 패키지 테스트들을 전부 Mockito로 바꿀려고 했는데, 오늘 안엔 다 못하겠군요. 오늘은 Mockito나 좀 더 공부하고 내일까지 해야겠네요.

expect -> run -> verify 스타일(ex. Easymock) 바이바이

참조 : http://monkeyisland.pl/2008/02/01/deathwish/

이지목 스타일은 녹화 -> 플레이 -> 확인(expect -> run -> verify) 순으로 mocking 또는 stubbing 하는 거였습니다. 그러나 이 스타일은 다음과 같은 단점들이 있습니다.

1. 테스트 메소드가 지져분해짐.
– 이것 저것 예측/녹화를 해줘야 하는데 그게 테스트를 위해서가 아니라 Mock을 위해서 해줘야 한다는게 좀..

2. 자연스러운 테스트 스타일로 느껴지지 않는다.
– 예측을 한 담에 실행하는게 아니라, 실행 한 다음에 예측되는 Mock의 행위를 나열해 주는게 더 자연스럽다.

3. 테스트가 깨지기 쉽다.
– 새로운 기능을 추가하면, Mock을 사용한 테스트가 왕창 깨지는 경우가 발생한다.

4. 보다 자세한 실패 메시지를 보여줄 수 있었을 텐데…

5. 보다 가독성 좋게 만들 수 있었을 텐데…

그래서 상태 기반 테스트를 제공하는 Mockito를 강추 한다는거…

Mockito 홈에서 다음을 인용합니다.

No expect-run-verify also means that Mockito mocks are often ready without expensive setup upfront. They aim to be transparent and let the developer to focus on testing selected behavior rather than absorb attention.

Mockito has very slim API, almost no time is needed to start mocking. There is only one kind of mock, there is only one way of creating mocks. Just remember that stubbing goes before execution, verifications of interactions go afterwards. You’ll soon notice how natural is that kind of mocking when test-driving java code.

즉 stubbing -> execution -> verification 라고 할 수 있겠네요. 훔.. 그래도 왠지 expect -> run -> verify 형태와 비슷해 보이네요.

사용법은 여기에 잘 나와있습니다.