easymockを利用してみる(2) – easymockのインストールとHelloWorld
Mock Objectツールは、interfaceを元にモックのインスタンスを生成するのが基本らしいが、easymockにせよjMockにせよ、classからモックインスタンス生成が可能になっている。今回はこの機能を利用する。
動作させるために、easymockのサイトにあるEasyMock2.5.2、Class Extension2.4、そしてcglibのサイトからcglib-nodep-2.2.jarの3点をクラスパスに設定すればよい。
次に、動作確認のため、dJUnitのサイトにあるHelloWorldをeasymockで動作させてみる。
1: import java.io.PrintStream;
2: import org.junit.After;
3: import org.junit.Before;
4: import org.junit.Test;
5: import static org.easymock.classextension.EasyMock.*;
6:
7: public class HelloWorldTest {
8:
9: private PrintStream mock;
10: private PrintStream original;
11:
12: @Before
13: public void setUp() {
14: mock = createMock(PrintStream.class);
15: original = System.out;
16: System.setOut(mock);
17: }
18:
19: @After
20: public void tearDown() {
21: System.setOut(original);
22: }
23:
24: @Test
25: public void testMain() {
26: mock.println("Hello World.");
27: replay(mock);
28: HelloWorld.main(null);
29: verify(mock);
30: }
31: }
dJUnitではPrintStreamクラス自体に作用できるので、「ソース例」の2番目のコード10行目
String arg = (String) getArgument("java.io.PrintStream", "println", 0);
でPrintStream#println(String)の引数に設定された文字列を取得できている。
一方、easymockでは、createMockメソッドで作成したモックオブジェクト(mock)を、System.setOutメソッドで標準出力に設定してやる必要がある(上コード10-13行目)。元々のSystem.outは、普段と何ら変わらないオブジェクトなので、動作を設定することは出来ないためだ。
その他補足すると、djUnitでjunit4相当の記述をしようと思うと、始めにMockObjectManager.initializeメソッドを呼ぶ必要があり[参考]、Virtual Mock Objectもいきなり利用できる(=いきなりクラスを差し替えられる)わけではない。
…とここまで書いて気付いたのだが、easymockでは、private methodやstatic methodに対する操作が行えない。上記のSystem.outのようなstatic fieldもそうだ(上の例ではたまたまsetterがあるので問題ないが)。
これらのmethod,fieldに対して操作しようと思うと、easymock(等)を拡張するPowerMock、JMockitやJMockitのページで参照されているいくつかのプロダクトがあるようだが、結局dJUnitとアプローチは変わらない様に見える。そうするとやはり実行速度がネックになりそうだ。
PowerMockはまさにdJUnitと同じような仕組みのようだ。JMockitのサイトのPowerMockについて、以下の記述がある。
PowerMock uses custom class loaders (usually one per test class) in order to generate modified versions of the mocked classes. Such heavy use of custom class loaders can lead to conflicts with third-party libraries, hence the need to sometimes use the
@PowerMockIgnore("package.to.be.ignored")
annotation on test classes.
ちなみにdJUnitでは、無視するパッケージはAntのxml、djunitタスクのプロパティに設定する(excludesPath)。
JMockitはjavaagentを利用しているようだが、やはり動作速度は遅いらしい。
JMockitをフルに使ったら、テスト時間が2sから7.2sに増加した。予想以上に遅い。
当初の目的である、クライアント/サーバ間の通信でサーバのモックを作成するという点についてはeasymockで問題ないと思うが、上記の点はどうしたものか。
« easymockを利用してみる(1) – Virtual Mock Object と Mock Object の違い | トップページ | NicoBrowser ver.0.2.0 待機時間の設定項目追加 »
この記事へのコメントは終了しました。
« easymockを利用してみる(1) – Virtual Mock Object と Mock Object の違い | トップページ | NicoBrowser ver.0.2.0 待機時間の設定項目追加 »
コメント