2015/10/11

Android: Local Firebase Server + Unit Test

Firebaseを無料Planで使うため, Unit Testで帯域を消費したくない.
Firebaseをローカルサーバで用意して, それと通信することでこれを回避する.

Robolectric(JVM)で試そうとしたが, サーバからonCompleteの応答が受け取れず, 現状Instrumentation Unit Testで試している.

Local Firebase Server

e2eのシナリオテスト用には十分なFirebase ServerがNode moduleとして提供されているのでそれを利用する.

npm install --save-dev firebase-server

firebase serverを起動するjsを用意する. ファイル名はlaunch_local_firebase.jsとでもしておく.

var FirebaseServer = require('firebase-server');
FirebaseServer.enableLogging(true);
new FirebaseServer(5000, 'test.firebase.localhost', {
  /* You can put your initial data model here, or just leave it empty */
});

Firebaseはホスト名にドットを2つ含んでいる必要があるためlocalhost:5000では接続できない.
Local Firebase serverはtest.firebase.localhostとして起動する.

Local Firebase Serverへの要求/応答をロギングするためにenableLogging(true)を指定しておくと便利.

ホストPCのhostファイルにtest.firebase.localhost127.0.0.1つまりlocalhostで接続できるように次の一行を追記する.
Macであれば/private/etc/hostsあたりにホストファイルがある.

127.0.0.1 test.firebase.localhost

あとは先ほど作成したlaunch_local_firebase.jsを起動する.

node launch_local_firebase.js 

これでLocal Firebase Serverの準備は完了.

Run AndroidTest

あとはAndroidからFirebaseへ接続するだけでよい. 接続先はローカルホストになるため,

new Firebase("ws://test.firebase.localhost:5000/");

としていする. ただしGenymotionはlocalhostに固有のIPが割り当てられているため下記とする必要がある点に注意.

new Firebase("ws://192.168.56.1:5000/");

RobolectricでFirebaseからのコールバックが発火しない問題があり渋々Instrumentation Testで実行しているが, 解決方法をご存知の方はご教授頂けると幸いです.

ちなみに, 簡易な確認でよければofflineモードでテストをパスする方法もあるが, 信用性の面で採用しなかった.

public static class DebugModule extends Module {

  public DebugModule(Context context) {
    super(context);
  }

  @Override Firebase provideFirebase() {
    Firebase.setAndroidContext(context);
    Firebase firebase = new Firebase(FirebaseConstant.DEBUG_URI);
    firebase.goOffline();
    return firebase;
    }
  }

以上.