Robolectric + ormliteでUnitテスト
や。何もしなくてもよかった。。
どうやってやるのが常道なのかなぁ、とか2時間近く調べて、ShadowSQLiteOpenHelperが絡んでくるんだろうな、というところあたりまではわかったけど、具体的にどうするのかわからなかった。
が、前述のとおり、結局何もしなくてもRobolectricがよろしくやってくれるのだった。なんてこった。とりあえず書いてみろって話ですよ。
そういや、ormliteについてはAndroidでSQLiteを使おうとしたときの情報源まとめで名前を出したくらいで、具体的に何も書いてないけど、このエントリに書いてあるリンクで事足りると思う。
DatabaseHelper.java
public class DatabaseHelper extends OrmLiteSqliteOpenHelper { private static final String TAG = DatabaseHelper.class.getSimpleName(); private static final String DATABASE_DIR = Environment.getExternalStorageDirectory().getPath() + FileManager.SQLite_DB_HOGE; private static final int DATABASE_VERSION = 1; public DatabaseHelper(Context context) { super(context, DATABASE_DIR, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) { try { Log.d(TAG, "create db table"); TableUtils.createTableIfNotExists(connectionSource, Hoge.class); } catch (SQLException e) { Log.e(TAG, "Could NOT create database."); } } @Override public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) { //To change body of implemented methods use File | Settings | File Templates. } public void clearAllTable() { Log.d(TAG, "clear db data"); try { ConnectionSource connectionSource = getConnectionSource(); TableUtils.clearTable(connectionSource, Hoge.class); // TODO run on thread SQLiteDatabase db = getWritableDatabase(); db.execSQL("vacuum"); } catch (SQLException e) { Log.e(TAG, e.getMessage()); } } }
というヘルパーがあって、Hoge関連のDaoとかビーン的なものはOrmliteのいうがままに作ってあって、で、テストコードはこんな感じ。
@RunWith(RobolectricTestRunner.class) public class HogeDaoImplTest { private DatabaseHelper databaseHelper; @Before public void setup() { databaseHelper = OpenHelperManager.getHelper(new Activity(), DatabaseHelper.class); } @After public void tearDown() { if (databaseHelper != null) { databaseHelper.clearAllTable(); OpenHelperManager.releaseHelper(); databaseHelper = null; } } @Test public void testFirst() throws Exception { HogeDao dao = databaseHelper.getDao(Hoge.class); Hoge hoge = new Hoge("fuga"); dao.create(hoge); List<Hoge> list = dao.queryForAll(); assertThat(list.size(), is(equalTo(1))); } @Test public void testSecond() throws Exception { HogeDao dao = databaseHelper.getDao(Hoge.class); Hoge hoge = new Hoge("fuga"); dao.create(hoge); List<Hoge> list = dao.queryForAll(); assertThat(list.size(), is(equalTo(1))); } }
という感じで、テストは動くしパスする。
ShadowSQLiteOpenHelperはインメモリなDBをエミュレートしてくれるらしくて、接続を切ればデータは全部パーになる。ので@Beforeでこういうふうにしておくと、毎回DatabaseHelper::onCreateが走ってTableUtils.createTableIfNotExists(connectionSource, Hoge.class);されて、1つのテストが終わるとDBは吹っ飛ぶので Afterで毎回データを消しておけば、テストの順番がどうであれ同じ結果がでるべきだよね思想に沿った感じになる。なってると思う。
※同一テストクラス内ではデータはパーにならなかった。この辺もうちょっと調べないと。。。とにかく、全部のテスト回すときなんかは全部のテストが終わるまではDBは生き残っているので、各テストでちゃんとデータは消しとかなければ駄目だし、auto-generateなidを使う時も、割り振られるIDを予測したテスト(例えばデータを1件入れたらそのIDは1と推測したテスト)を書くといつかコケるので・・・。
まぁ、テーブルが複数あると毎回全部テーブル作られちゃうのがちょっとムダだけど。インメモリだから早いし、そもそも僕は4個くらいしかテーブルないからなんともない。
あとOpenHelperManager.getHelper(new Activity(), DatabaseHelper.class);のところでnew Activity()ってなんとなくやってるんだけど、これがあるべきなのかはよくわからない。引数として求められているから適当に充ててあるだけ。
こうやるべき、的なのがあったら教えてくださいん!