[Mockito] mock 객체 쉽게 만들기

이지목(easymock)을 사용할 때는 인터페이스의 목만 만들 수 있어서 불편했습니다. 물론, 이지목 확장팩(?)을 이용하면 클래스의 목객체도 만들 수 있었는데, 별도의 라이브러리를 추가해야 하는것이.. 좀 귀찮았죠. 요즘은 어떤지 몰겠습니다. 라이브러리 버전 올리면서 통합 할 법도 한데 말이죠.

암튼.. 저는 이지목보다 조금 더 간편하고 직관적인 라이브러리인 목킷투를 사용하고 있었는데, 예전에 살짝 공부한 상태에서 다시 별로 안 썼더니 그새에 많은 변화가 있었더군요. 그 중 가장 큰 변화가 애노테이션인 듯 한데요. 애노테이션을 이용해서 목객체를 아주 편리하게 만들 수 있었습니다.

@RunWith(MockitoJUnitRunner.class)
public class MemberServiceTest {

    MemberService memberService;
   
    @Mock MemberRepository mockMemberRepository;
    @Mock SignupSendService mockSignupSendService;

    @Before
    public void make() throws Exception {
        memberService = new MemberService();
        memberService.repository = mockMemberRepository;
        memberService.signupSendService = mockSignupSendService;
        assertNotNull(memberService.repository);
        assertNotNull(memberService.signupSendService);
    }

}

끝입니다. mock(MemberReposiroty.class); 같은 static 메서드 호출(이클립스에서 junit은 static import를 지원하지만 mockto는 지원하지 않아서 수동으로 static import 문을 적어줘야 하는 수고가 있죠.) 없이도 목 객체를 만들어(?) 사용할 수 있습니다. 그 비밀은 바로 @Runwith의 MockitoJUnitRunner에 있지요. 저 러너 설정하는 것이 귀찮다면 JUnit @Before 메서드에서 MockitoAnnotations.initMocks(this); 를 직접 호출해도 되지만, 개인적으로는 이걸 없애고 @RunWith를 사용하는 편이 코드가 더 깔끔한 듯 합니다.

목킷투~ 괜찮다~~

[Mockito] void 메서드 stubbing 새로운 방법

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

링크에 있는 글대로 작성 해 보면

        stubVoid(mockWarManager).toThrow(new WarPackgingException()).on().packaging();

이렇게 됩니다.

“누가 뭘 던 진다 뭐 할 때.”

새로운 형태로 작서한 코드는 다음과 같습니다.
       
        doThrow(new WarPackgingException()).when(mockWarManager).packaging();

“이걸 던진 다. 누가 뭐 할 때”

후자가 조금 더 짧죠.

ps: 매녈 좀 업데이트 해주시지 말입니다. 스프링은 매녈이 소스 코드를 앞서 간다는데…

Why OSAF 1. 테스트 코드를 익힐 수 있습니다.

OSAF를 공개한지 한 달이 아직 안 됐습니다. 10월 23일에 공개했었죠. 지금까지 약 200에 가까운 다운로드를 기록하고 있지만, 전혀… 아무런… 반응이 없다는 것에는 가히 놀라울 뿐입니다. 그냥 제가 쓴 글의 댓글 몇 개 정도 뿐의 관심이 저에게 한 편으로는 아쉬움으로 또 다른 한 편으로는 오기로 다가옵니다.

완전 최첨단 프레임워크인 OSAF에 왜 이렇게 관심이 없을까. 고민을 많이 했습니다. 어렵나? 메이븐 떄문인가? 그거 없어도 되는데. 문서가 부족하긴 부족하고. 그래도 어떻게 이렇게 조용할 수가 있지. 홈피 디자인이 좀 구리긴 한데.. 그거 때문인가? ㅋ. OSAF 발음이 너무 어려운가? 별에 별 생각을 많이 했습니다. 당연히 기운도 빠집니다. OSAF를 공개한 건 어쩌면 OSAF에게 못씁짓을 한 건 아닌지 말이죠.(Max님의 ‘어디가서 밥은 먹고 다녀야 할텐데..’ 라는 댓글이 생각납니다.)

긍정적으로 생각하기로 했습니다. 언젠가는 빛을 보겠지. 열심히 계속 가꾸다 보면 언젠간 알아주겠지. 하고 말이죠. 그래서 OSAF가 여러분에게 어떤 도움을 줄 수 있을지 생각하고 알려드리기로 했습니다. 그 중 첫 번째가 바로 테스트 코드입니다.

OSAF의 테스트 커버리지는 60%가 조금 넘습니다. (앞으로 차차 올릴 예정입니다.) 60%의 테스트 커버리지는 전부 OSAF 개발팀에서 직접 작성한 테스트 코드입니다. 어딘가에서 배껴온 코드가 절대로 아닙니다. 테스트는 초기에 JUnit과 EasyMock을 사용해서 작성 했었습니다. 물론 스프링 테스트 기능도 사용하고 있죠. 배포 직전에는 EasyMock을 Mockito로 교체하여 비슷한 테스트를 보다 깔끔하고 직관적이며 적은 수의 코드로 대체할 수 있었습니다. DBUnit을 확장하여 OSAF가 제공하는 테스트 케이스를 이용하면 DAO 테스트가 매우 간편해질 것 입니다.

이렇게 좋은데… 한 번 들여다 보고 뭐라고 해주시지 않으시겠어요? 좋다. 잘했다. 고맙다. 이런거 말구요. 이 부분의 테스트는 이해가 안 된다. 테스트가 조금 이상하다. 이 부분의 테스트는 왜 안했냐. 어려워서 그런거냐? 이 부분의 테스트는 이렇게 고치는게 좋치 않겠냐? 이런.. 반응이 제가 가장 좋아하는 반응이자 OSAF에게 거름을 주는 방법입니다.

소스 코드는 굳이 다운 받지 않아도(장기적으론 받아 두시면 좋겠지만..)

http://www.opensprout.org:9060/browse/OSAF/osaf/trunk

위 링크로 가시면 웹에서 직접 볼 수 있습니다. 소스 코드나 OSAF 와 관련하여 문제나 제안하고 싶은 것이 있다면 주저하지 마시고 이슈를 등록해 주세요.

http://www.opensprout.org/jira/secure/Dashboard.jspa

Mockito – 아규먼트 Matcher

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

  // 내장된 anyint() 아규먼트 매처를 사용해서 스텁 만들기.
  stub(mockedList.get(anyInt())).toReturn(“element”);
 
  // hamcrest가 제공하는 매처를 사용해서 스텁 만들기.
  stub(mockedList.contains(argThat(isValid()))).toReturn(“element”);
 
  // 다음은 “element”를 출력한다.
  System.out.println(mockedList.get(999));
 
  // 아규먼트 매처를 사용해서 verify()를 할 수도 있다.
  verify(mockedList).get(anyInt());
 
아규먼트 매처는 flexible한 검증과 스텁을 제공한다. 전체 매처는 여기서 확인할 수 있다.

주의할 것:

아규먼트 매처를 하나 사용하면, 다른 아규먼트들도 모두 매처로 표현해야 한다.

예:

   verify(mock).someMethod(anyInt(), anyString(), eq(“third argument”));
   // 위와 같이 사용해야 한다. eq()도 아규먼트 매처니까 괜찮다.
  
   verify(mock).someMethod(anyInt(), anyString(), “third argument”);
   // 이렇게 하면 안 된다. 아규먼트 매처없이 사용한 세번째 아규먼트 때문에 예외가 발생할 것이다.

Whiteship’s Exercise

    @Test
    public void ilike() {
        Criteria c = mock(Criteria.class);
        CriteriaUtils.ilike(c, “name”, “keesun”, MatchMode.ANYWHERE);
        verify(c).add((Criterion) anyObject());
    }

    @Test
    public void ilikeWithNullValue() {
        Criteria c = mock(Criteria.class);
        CriteriaUtils.ilike(c, “name”, null, MatchMode.ANYWHERE);
        verify(c, never()).add((Criterion) anyObject());
    }

Mockito – Verifying exact number of invocations / at least once / never

Mockito 사용해서 정확한 메소드 호출 횟 수 / 최소한 한 번 / 전혀~ 한 번도 호출 안했는지 검증하기

  //mock 사용하기
  mockedList.add(“once”);
 
  mockedList.add(“twice”);
  mockedList.add(“twice”);
 
  mockedList.add(“three times”);
  mockedList.add(“three times”);
  mockedList.add(“three times”);
 
  //다음 두 번의 검증은 똑같다. 기본으로 times(1)를 사용하기 때문에..
  verify(mockedList).add(“once”);
  verify(mockedList, times(1)).add(“once”);
 
  //정확한 호출 횟 수 검증
  verify(mockedList, times(2)).add(“twice”);
  verify(mockedList, times(3)).add(“three times”);
 
  //neber()를 사용한 검증, times(0)과 같다.
  verify(mockedList, never()).add(“never happened”);
 
  //atLeastOnce()를 사용한 검증
  verify(mockedList, atLeastOnce()).add(“three times”);
 
Whiteship’s Exercise

EasyMock Code

    @Test
    public void delete() {
        Member member = new Member();
        mockDao.delete(member);

        replay(mockDao);

        service.delete(member);

        verify(mockDao);
    }

Mockito Code

    @Test
    public void delete() {
        Member member = new Member();
        service.delete(member);
        verify(mockDao).delete(member);
    }