NetBeansでdjUnit的なこと

昨日、「続きは明日書きます」とかいいつつ今日は全く違うネタを書こうとしている私が来ましたよ。

昨日の続きはまた明日書くとして(おい)。

私は、djUnitを結構気に入っているのです。というか、Virtual Mockを結構気に入っているのです。interfaceの挙動しか弄れないEasyMockと違って、実クラスも弄れるところがスバラスィ。ついでにカバレッジを取ってくれるところもまたスバラスィ。Cactusとかで頑張らなくてもWeb層のテストも比較的余裕。カバレッジ100%も夢じゃない(まぁ実プロジェクトで実際100%目指すのは大変ですけど)。

でも、djUnitのサイトを見るに、Eclipse用のプラグインはあってもNetBeans用のプラグインは無さげ。例によって、antなりmavenなりでの実行で代用することもできますが、それだと普通にやると毎回全クラスのテストケースを実行してしまうのもちょっと辛い。開発時はやっぱ、簡単に1クラスづつテストケースを実行できた方がらくちん。

そんな訳で、なんとかVirtual Mock単体で利用する方法を探すことにしてみました。カバレッジはなんか、他にそれらしい機能がNetBeansにもありそうだし。

そんなこんなで、色々ぐぐってみると。なんだか、

JMockit最強

とかブログで言ってる人がいるじゃありませんか。一方、Virtual Mockの方はぱっとそれらしいものは出てきません(私のググリ方が悪いだけかもしれませんが)。そんな訳で、あっさり路線変更。JMockitを試してみることにしました。この際、実クラスの振る舞いを弄れるMockであればなんでもいいです。

セットアップ方法はとりあえず以下の通り簡単。

  • 以下のJMockitのサイトからzipをダウンロード
  • zipを解凍し、とりあえず「jmockit.jar」だけをNetBeansプロジェクトの「テストライブラリ」に追加
    • ときに、「テストライブラリ」に追加したjarは、実際NetBeansプロジェクトの何処に追加されるんだ?
    • と、思ったら、元々jarが存在していたパスへの参照が追加されるだけで、jarファイル自体がインポートされる訳ではないのですね。
    • nbproject/project.properties内にこんな記述を発見。
  • プロジェクトを右クリックしてコンテキストメニューを表示し、「プロパティ」を開く
  • 「実行」のところの「VMオプション」に以下のような設定を追加
    • -javaagent:/(jmockit.jarへのフルパス)/jmockit.jar=junit3
      • フルパスで指定しないといけないところがちょっぴりいただけない。なんとかプロジェクト相対とかで指定できないものか。
      • ついでにいうと、テスト実行時のみのVM引数とか指定できたりしないものか。

さて、実験。とりあえずJMockitで弄るための適当サービスとして、こんなクラスを作成。

package test;

public class Service {
    public String execute() {
        return "original.";
    }
}

適当さあふれるクラスですね。次に、こんな感じでテストクラスを作成。

package test;

import junit.framework.TestCase;
import mockit.Mockit;

public class ServiceTest extends TestCase {
    public void testExecute() {
        Mockit.redefineMethods(Service.class, new Object() {
            public String execute() {
                return "redefined.";
            }
        });
        
        Service service = new Service();
        String result = service.execute();
        System.out.println(result);
    }
}

Mockit.redefineMethodsが、JMockitによるMock設定の部分ですね。さて、実行してみると・・・

Loaded external tool: mockit.integration.junit3.JUnitTestCaseDecorator
Loaded external tool: mockit.integration.junit4.JUnit4ClassRunnerDecorator
redefined.

おぉぉぉぉぉぉぉっ!

見事に、オリジナルのServiceの「original.」という実行結果では無く、テストケース内で弄った「redefined.」という実行結果がログ出力されていますね。なんだか上手くいってそげです。djUnit + Virtual Mockとの主な違いとしては、

  • Virtual Mockがリフレクションチック(?)な弄り方なのに対して、JMockitは無名クラスチックな弄り方
    • 好みの差もあるとは思いますが、私は後者の方がなんか直感的で自由度も高そうで分かりやすい気が。
    • 逆に、前者の方が記述量は少なそうではありますが。
  • djUnitは独自のテストケースを継承しなければならないのに対し、JMockitは特に独自の継承元を持たない。
    • よって、DbUnitやSpringのDBテスト用のテストケース(長過ぎてクラス名を忘れました)でも利用できる(即ち、正常系のCRUDテストと、Virtual Mockを使わないと発生し得ないような異常系のテストを同一のテストクラス中で実行可能)し、JUnit4みたいに継承元がない場合でも利用できる。

ってところでしょうか。後は、この辺のやり方でも分かれば、NetBeansJMockitでもEclipse+djUnitプラグインと同等のことができそうな気がしてきました。

  • メソッド呼び出し時の引数を確認する
  • メソッドの呼び出し回数を確認する

それにしても、JMockitってなんて読むんでしょう?

  • ジェイモックキット?
  • ジェイモックイット?
  • ジェイモキット?

ただ一つ残念な点を言えば、JMockitdjUnit同様mavenのセントラルリポジトリにjarが登録されていないところでしょうか。mavenerな私としては非常に残念なところです。でも、NetBeansmavenプラグインだと、eclipseと比べて比較的ローカルリポジトリでの管理も楽そう(な、感じがする)し、まぁよしとします。