Mockitoの実験(モックを用いた単体テスト)

さて、結構サンプルが転がってるわけですが、(公式のドキュメントもしっかりしているし?)
なんとなく古い人間としては、全Mocというよりは、spyがキモになるんじゃないのかなぁ?なんて思ったり。
もっとも、最近のDI全盛においては全mocをDIするといったケースが多々あるのでその限りではございませんが・・・


ひとまず、古い人間にjunitでモックのテストを書け。となるとこんな感じか・・
以下の様なLogicとDaoがあって、daoが未完成で、Logicの計算部分のテストがしたい。

package logic;

import dao.SettingsDao;

public class CalcLogic {
  /**
   * 設定の税率で金額を求め、送料を付与して返す。
   * 
   * @param price 金額
   * @return 合計金額
   */
  public int calcPrice(int price) {
    //インラインでインスタンスを取得しているのでMoc化できない。
    //SettingsDao settingsDao = new SettingsDao();
    // メソッド化
    
    SettingsDao settingsDao = getInstance();
    return (int)Math.floor(price * (1 + settingsDao.getTaxRate())) + settingsDao.getTransportation();
  }
  
  /**
   * 設定情報取得Daoを返却する。
   * @return
   */
  protected SettingsDao getInstance() {
    return new SettingsDao();
  }
}
package dao;

public class SettingsDao {
  /**
   * DBより税率を取得して返す。
   * @return 税率
   */
  public double getTaxRate() {
    return 0.5;
  }
  
  /**
   * DBより送料を取得して返す。
   * @return 送料
   */
  public int getTransportation() {
    return 500;
  }
}

そんでもって、テストはこんな感じ

package logic;

import static org.junit.Assert.*;

import org.junit.Test;

import dao.SettingsDao;

public class CalcLogicTest {

  @Test
  public void testCalcPrice() {
    CalcLogic logic = new CalcLogic() {
      @Override
      //DaoのMocを返す。
      protected SettingsDao getInstance() {
        return new SettingsDao() {

          @Override
          public double getTaxRate() {
            return 0.03;
          }

          @Override
          public int getTransportation() {
            return 200;
          }
          
        };
      }
      
    };
    
    int calcPrice = logic.calcPrice(200);
    assertEquals(406, calcPrice);
  }

}

これをMockItoを使ってみるとこんな感じかな?

package logic;

import static org.junit.Assert.*;
import org.junit.Test;
import dao.SettingsDao;
import static org.mockito.Mockito.*;
public class CalcLogicMockItTest {
  @Test
  public void testTestCalcPrice() {
    CalcLogic logic = spy(new CalcLogic());
    SettingsDao dao = spy(new SettingsDao());
    
    when(dao.getTaxRate()).thenReturn(0.03);
    when(dao.getTransportation()).thenReturn(200);

    when(logic.getInstance()).thenReturn(dao);
    int calcPrice = logic.calcPrice(200);
    assertEquals(406, calcPrice);
  }

//個人的には以下も慣れていてすきですが中途半端ですやね。
  @Test
  public void testTestCalcPrice_個人的には好きなテスト() {
    CalcLogic logic = spy(new CalcLogic());
    
    when(logic.getInstance()).thenReturn(new SettingsDao() {

          @Override
          public double getTaxRate() {
            return 0.03;
          }

          @Override
          public int getTransportation() {
            return 200;
          }
          
        });
    int calcPrice = logic.calcPrice(200);
    assertEquals(406, calcPrice);
  }

}

見た目的にはかなりすっきりしたのではないでしょうか。
下のテストは気にしないでください。個人的には好きなだけですので。