最近、既存コードのテストコードを書きまくっています。
その中で、Easymock(classExtension)などを用いてMock化している場合に、
finalクラスをMock化できず困っていました。
何かいい方法がないかなと思っていたらhudsonの開発者である川口さんが
jaavassistを利用してfinalを除去しているという記事があり、
なるほどと思って自分もその方向で対応を行うことにしました。
その際に「なぜテストを書くのか」「どうしてそんな書き方をするのか」
ということを色々考えていたので、簡単に脳みそを整理してみます。
バイトコードが使われるとき
主にフレームワーク内部やIDEで利用されている技術と聞いています。
つまり大多数の一般的な開発者には使われないという認識です。
なぜテストにおいてバイトコード操作やリフレクションを使うのか
私の主観としては、リフレクションやバイトコード操作は通常の業務アプリケーションの実装で
頻繁に使うべきでないと考えています(少なくとも自分の周囲の現場では)。
理由としては以下のようなものが挙げられます。
- パフォーマンスの問題
- ソースコード可読性の低下
- IDE(eclipseなど)によるサポートが追いついていない
- 技術レベルの要求
- リフレクションやバイトコードを操作するくらいなら設計を見直すべき
その一方で、テストコードにおいては積極的に活用すべき技術だと思います。
レガシーコード(ここでは古いコードの意味でなく「テストコードがないプログラム」という意)は、
テスタビリティが低く実装されていたため、
既存のプログラムが正常に動くことを保障した上でリファクタリングを行う必要がありました。
※テストによってセーフティネットを提供する必要が大前提としてあるからと考えています。
byteコード操作
javaのバイトコードを理解せずにバイトコード操作を行うことは自分には敷居が高いため、
javassistというライブラリを利用させていただきました。以下のリンクに詳しく説明が書かれています。
- http://www.csg.is.titech.ac.jp/~chiba/notes/javapress03/index.html
- http://www.smg.co.jp/seminar/techsquare/javassist01.html
- http://www.ne.jp/asahi/hishidama/home/tech/java/javassist.html
自分が必要になった状況
テスト時にバイトコード操作が必要になった状況は以下のような状況でした。
- finalクラスをmock化したい(Easymockではfinalクラスをmock化できない)
- privateメソッドをmock化したい
javassistのライセンス
MPL (Mozilla Public License) と LGPL (GNU Lesser General Public License) のデュアルライセンスだそうです。
テストコードですのでリリース時はアプリケーションに同梱しなければ問題ないと思いますが、
注意しておきたいところです。