mockito(1) スタブ的に使う
DAO依存のクラステストが面倒
テスト対象のクラスAがDAOクラスBに依存しているような場合、テストデータをDBにあらかじめ登録する必要がある。
dbunitのようなファイルからレコードを読み込むフレームワークはあるが、DAOではないクラスAのテストのためにレコードを仕込むのは面倒。
mockitoを使う
レコードをいちいち仕込むのは面倒なのでスタブを作成して、実際のメソッドをテストデータ呼び出しのメソッドに置き換える。
ここでmockitoフレームワークを使用する。
準備
今回はmavenを使用せず、手作業でライブラリを導入する。
公式から下記をダウンロード。
-
- mockito-core-2.0.29-beta.jar
mavenリポジトリにアクセスして、依存するライブラリをダウンロード。
依存関係にあるライブラリは「maven-metadata.xml」参照。
-
- byte-buddy-0.6.11.jar
- objenesis-2.1.jar
ビルドパスに外部jarとして追加。
実際に使ってみる
Userテーブルを操作するUserDaoとUserDaoを使用するUserLogicを用意。
ここではUserDaoをモックして、テストデータを返すようにした。
モックの作成方法、注入方法は複数あるが、下記以外はモックが注入されないなどうまくいかなかった。
UserLogicテストケース。
package jp.ne.hatena.matasaburou.logic; import static org.junit.Assert.*; import static org.mockito.Mockito.*; import java.util.ArrayList; import java.util.List; import jp.ne.hatena.matasaburou.dao.UserDao; import jp.ne.hatena.matasaburou.entity.UserEntity; import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; public class UserLogicTest{ @Mock private UserDao dao; @InjectMocks private UserLogic target; @Before public void setup(){ MockitoAnnotations.initMocks(this); } @Test public void test_findAll_ok() throws Exception{ List<UserEntity> list = new ArrayList<>(); list.add(createEntity("takeda",0)); list.add(createEntity("sanada", 1)); when(dao.findAll()).thenReturn(list); List<UserEntity> result = target.findAll(); assertEquals(2, result.size()); } public UserEntity createEntity(String name, int sex){ UserEntity entity = new UserEntity(); entity.setName(name); entity.setSex(sex); return entity; } }
UserDaoクラス。(適当)
package jp.ne.hatena.matasaburou.dao; import java.sql.Connection; import java.sql.DriverManager; import java.util.ArrayList; import java.util.List; import jp.ne.hatena.matasaburou.common.dao.AbstractDao; import jp.ne.hatena.matasaburou.entity.UserEntity; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.ResultSetHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; public class UserDao extends AbstractDao { public int insert(UserEntity entity) throws Exception{ Class.forName("org.mariadb.jdbc.Driver"); Connection con = DriverManager.getConnection("jdbc:mariadb://localhost:3306/daotraining", "root", "root"); QueryRunner q = new QueryRunner(); List<Object> fieldValue = new ArrayList<Object>(); fieldValue.add(entity.getName()); fieldValue.add(entity.getSex()); int result = q.update(con, "insert into user (name, sex) values(?, ?)", fieldValue.toArray()); return result; } public List<UserEntity> findAll() throws Exception{ Class.forName("org.mariadb.jdbc.Driver"); Connection con = DriverManager.getConnection("jdbc:mariadb://localhost:3306/daotraining", "root", "root"); QueryRunner q = new QueryRunner(); ResultSetHandler handler = new BeanListHandler(UserEntity.class); List<UserEntity> list = (List<UserEntity>)q.query(con, "SELECT * FROM USER", handler); return list; } }
UserLogicクラス。(適当)
package jp.ne.hatena.matasaburou.logic; import java.security.InvalidParameterException; import java.util.List; import jp.ne.hatena.matasaburou.dao.UserDao; import jp.ne.hatena.matasaburou.entity.UserEntity; public class UserLogic { private UserDao dao; public UserLogic() { dao = new UserDao(); } public void insertData(UserEntity entity) throws Exception{ if(entity == null){ throw new InvalidParameterException("entity is null."); } int result = dao.insert(entity); if(result != 1){ throw new Exception("insert userData failed."); } } public List<UserEntity> findAll() throws Exception{ return dao.findAll(); } }
UserEntityクラス
package jp.ne.hatena.matasaburou.entity; public class UserEntity { private long no; private String name; private Integer sex; public long getNo() { return no; } public void setNo(long no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } }