JMockitの使い方


テストクラスを書くときに使いそうなので事前に調査した。
調べたのは下記の通り

- Springを使ってるのでDIしている箇所がモックにできるか
- staticメソッドの戻りもモックにできるか
- new Date()...の戻り値もモックにできるか

結論：できた。
これ1つで全部まかなえたのは結構大きいかもしれない。できないことはなんだろうか？？

```java:テストクラス
package com.hachiyae.jmockit;

import mockit.Expectations;
import mockit.Mock;
import mockit.MockUp;
import org.junit.Test;

import java.util.Calendar;
import java.util.Date;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

public class TesterServiceTest {
    private TesterService tester = new TesterService();


    @Test
    public void testSayHello() throws Exception {
        String message = tester.sayHello("user1");
        assertThat(message, is("Hello user1"));
    }

//    // これでもOK
//    @Mocked
//    private CurrentDateFactory currentDateFactory;

    // 引数でもいいよ
    @Test
    public void testSayCurrentDate(final CurrentDateFactory currentDateFactory) throws Exception {
        new Expectations() {
            // ここにつけてもいいよ
//            CurrentDateFactory currentDateFactory;
            {
                setField(tester, currentDateFactory);
                Calendar calendar = Calendar.getInstance();
                calendar.clear();
                calendar.set(2014, 0, 1);
                // 直後にresultに値を入れることでモックの戻り値を定義
                // timesは回数(1の時は省略
                currentDateFactory.getCurrentDate(); result = calendar.getTime(); times = 1;
            }
        };
        String message = tester.sayCurrentDate();
        assertThat(message, is("current date is 2014/01/01"));
    }


    @Test
    public void testSayCurrentTime() throws Exception {
        // static method
        new Expectations() {
            // 無駄にモックオブジェクトインスタンスを生成しない
            final TestUtils testUtils = null;

            {
                Calendar calendar = Calendar.getInstance();
                calendar.clear();
                calendar.set(2014, 0, 1, 1, 2, 3);
                testUtils.getCurrentDate(); result = calendar.getTime();
            }
        };
        String message = tester.sayCurrentTime();
        assertThat(message, is("current time is 01:02:03"));
    }

    @Test
    @SuppressWarnings({"unused", "deprecation"})
    public void testSayCurrentYear() throws Exception {
        new MockUp<System>() {
            @Mock
            public long currentTimeMillis() {
                return new Date(110, 0, 1).getTime();
            }
        };
        String message = tester.sayCurrentYear();
        assertThat(message, is("current year is 2010"));
    }
}

```

```java:テスト対象クラス
package com.hachiyae.jmockit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;

@Service
public class TesterService {
    @Autowired
    private CurrentDateFactory currentDateFactory;

    public String sayHello(String userName) {
        return "Hello " + userName;
    }

    public String sayCurrentDate() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
        return "current date is " + format.format(currentDateFactory.getCurrentDate());
    }

    public String sayCurrentTime() {
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        return "current time is " + format.format(TestUtils.getCurrentDate());
    }

    public String sayCurrentYear(){
        SimpleDateFormat format = new SimpleDateFormat("yyyy");
        Date date = new Date();
        return "current year is " + format.format(date);
    }
}
```

```java:テスト対象クラスから呼ばれるService
package com.hachiyae.jmockit;

import org.springframework.stereotype.Service;

import java.util.Date;

@Service
public class CurrentDateFactory {
    public Date getCurrentDate(){
        return new Date();
    }
}

```

```java:テスト対象クラスから呼ばれるstatic
package com.hachiyae.jmockit;

import java.util.Date;

public class TestUtils {
    public static Date getCurrentDate (){
        return new Date();
    }
}

```


参考URL:

- JMockit  
https://code.google.com/p/jmockit/
- 次世代のモックフレームワークであるJMockitの基本的な使い方
http://d.hatena.ne.jp/ryoasai/20110107/1294427245
- How to mock the default constructor of the Date class with JMockit?
http://stackoverflow.com/questions/4563584/how-to-mock-the-default-constructor-of-the-date-class-with-jmockit