2015年8月24日月曜日

JUnitでHBaseクライアント側を通す - How to test HBase in Unit Test process (client side)

jUnitでHBaseの擬似HTableをつくってUnit Testを通すやり方。

HBaseにつなぐソースのユニットテストを、実際のHBaseに
繋がずに通したいときに、擬似HTable(モック)を作成して
通す方法。

簡単に言うと
①HConnectionを偽装
②偽装HConnectionを使用してHTableを偽装
となる。
また、おまけで
③Scan時に擬似データを返すように擬似データを登録
することも可能。

※①②ともHBaseの内部の処理を通るため作成には
数十秒かかる。そこで通るタイムアウト絡みの
パラメータを乗っ取れば(リフレクション)高速化できる
のであろうが、そこまでは追わなかった。

いろいろ試した結果、この方法に辿り着いた。

一応試行の遍歴を記すと、
・実際にHBaseに接続した時のHTableオブジェクトを
 シリアライズ化して保存し、それを復元する試行。
→引数なしのHTableコンストラクタが定義されてないので
 エラー。

※そもそもシリアライザを継承してないのでシリアライズしても
 表面上のパラメタだけしか取得できない。
 そこでJSON化を試し、それなりの情報が取得でき、それの
 復元化(復元マッパの登録)まで出来たが、やはり最後は
 コンストラクタ呼び出しがされるので、引数なしコンストラクタ
 未定義でエラー。

ダメかと思ったが、HTableはHConnectionを引数にするコンストラクタが
あるのでHConnectionの偽装、それを使用してしかも -ROOT- を指定する
ことでHTableのコンストラクタを通すことができた。

HBase、Hadoopを内部から理解されてる方ならHBaseクライアントの
Unit Test方法は一般的なのかもしれないが、取っ掛かもなくいきなり
HBaseクライアントのUnit Testをする必要が生じた方々はこれを
参考にしていただければ。一助になれば。

以下、テストクラスのコードサンプル。
// Prepare the configuration
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "127.0.0.1");

// 1.Create HConnection - HConnectionの作成
HConnection con = ... 
// make HTable with table name "-ROOT-" and set isClosed to false.
// prepare class loader
// get inner HTable's implemented class
// get "isClosed" member
Field fld = cls.getDeclaredField("isClosed");
fld.setAccessible(true);
fld.set( ... 

// 2.make HTable mock with -ROOT- table , so that it will work.
// 「-ROOT-」テーブルのHTableモックの作成。 
HTable tbl = new HTable("-ROOT-", con);

// 3. you can put the data of htable with reflection.