16 Dec 2012, 23:02

JMockのインストールとEclipseでの使い方まとめ

JMockとは、JAVAでモックオブジェクトを簡単に作成するためのフレームワーク。
モックオブジェクトを利用すると、以下のことが簡単にテストできる。

  • メゾッドが何回呼ばれたか。
  • メソッドがどんな引数で呼ばれたか。
  • メソッドから任意の値を返す。
  • メゾッドがどんなシーケンスで呼ばれたか。

などなど。他にもできることはたくさん。

JMockの設定方法

JMockのダウンロード

以下のサイトより、ダウンロード。
ここでは、最新安定版の 2.5.1 jmock-2.5.1-jars.zipを落とす。

jMock – Downloads

Eclipseでビルド・パスを通す

ダウンロードしたzipファイルを解凍し、任意の場所に置く。
(ここでは、jmockと名前を変更してC:\src\jmockにおいた)

EclipseからJMockライブラリを利用するために、ビルド・パスを通す。
プロジェクトを選択して、[ブロパティ] > [Javaのビルドパス]を選択。
[ライブラリ]タブ > [ライブラリの追加] > [ユーザライブラリ] > [次へ]
[ユーザライブラリ] > [新規]を選択。

ライブラリを作成するために、[JMock2]と名前をつける。
続いて、[外部Jar追加]。ここでは、以下のJarを追加。

  • jmock-2.5.1.jar
  • jmock-junit4-2.5.1.jar
  • hamcrest-library-1.1.jar
  • hamcrest-core-1.1.jar

JMockを動かしてみる

JMockを動かしてみる。JMockを利用するためには、テスト対象のコードは以下。

public class Sample {

    private External external;

    public int num() {
        return external.get_num();
    }

    public void setExternal(External external) {
        this.external = external;
    }
}

インタフェースの用意

JMockを利用してモックオブジェクトを作成するためには、

クラスのメソッドがインタフェース化されている必要がある。

インタフェースを利用することで、『実体』と『モック』を置き換えることができる。

public interface External {
    int get_num();
}

テストコードの追加

続いて、テストコードの追加。ここでは、1回呼ばれることを検証している。oneOf

されに、生成されたモックの戻り値として返して貰いたい数字を指定している(10)

import static org.junit.Assert.*;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(JMock.class)   // TestRunnerを使う宣言
public class mock_sampleTest {
    private final Mockery context = new JUnit4Mockery(); //モッカリー生成
    private External external;
    private Sample impl;

    @Before  // 事前処理宣言
    public void setUp() throws Exception {
        external = context.mock(External.class);  //インタフェースのモック生成
        impl = new Sample();                       //テスト対象の宣言
        impl.setExternal(external);
    }

    @Test
    public void firstMockGenerate() {
        context.checking(new Expectations() {{
            oneOf(external).get_num();      //1回呼びだされる
            will(returnValue(10));          //10を返す
        }});
        assertEquals(10, impl.num());       //メソッド呼び出し
    }
}

モッカリーとは、テスト実行中にモックを呼び出す。

モッカリーやモック生成は定型文なので、コピペで。

テストを実行すると、グリーンバーが出てテストが成功することがわかる。

おまけ

Eclipseだと、もともと入っているJUnitとJMockでのものが競合する場合がある。

そんなときは、以下の解決方法を参照。

EclipseにJMockを入れてSecurityExceptionが発生。

10 Dec 2012, 23:37

EclipseにJMockを入れてSecurityExceptionが発生。

EclipseにJMockを入れたところ、java.lang.SecurityExceptionという例外が発生した。

java.lang.SecurityException: class “org.hamcrest.TypeSafeMatcher”‘s signer information does not match signer information of other classes in the same package at java.lang.ClassLoader.checkCerts(ClassLoader.java:943) at java.lang.ClassLoader.preDefineClass(ClassLoader.java:657) at java.lang.ClassLoader.defineClass(ClassLoader.java:785) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:423) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:791) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:423) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) at org.jmock.internal.InvocationExpectationBuilder.createExpectationFrom(InvocationExpectationBuilder.java:86) at org.jmock.internal.InvocationToExpectationTranslator.invoke(InvocationToExpectationTranslator.java:19) at org.jmock.internal.FakeObjectMethods.invoke(FakeObjectMethods.java:38) at org.jmock.lib.JavaReflectionImposteriser$1.invoke(JavaReflectionImposteriser.java:33) at $Proxy8.someExternal(Unknown Source) at mock_sampleTest$1.(mock_sampleTest.java:45) at mock_sampleTest.testSome(mock_sampleTest.java:44) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66) at org.jmock.integration.junit4.JMock$1.invoke(JMock.java:37) at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:105) at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86) at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94) at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84) at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49) at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:98) at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:61) at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:54) at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34) at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44) at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:52) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

環境

  • Eclipse 4.2
  • JUnit 4
  • JMock2

原因

EclipseのJUnitプラグインに含まれるHamcrestと、jMockのHamcrestのバージョンが異なっているみたい。

EclipseをダウンロードしてきたときのデフォルトJUnitにJMockを追加したら発生した。

解決方法

このページを参考 :

http://stackoverflow.com/questions/4755442/jmock-dependency-issue

以下の解決方法が提示されている。

  • junit.jarの代わりに、junit-dep.jarを使う
  • Eclipseのビルド・パスで、hamcrest.jarをJUnitライブラリの前ではなく、あとに並び替える。

The solution is simple – make sure that hamcrest.jar is before the JUnit library included by Eclipse in the classpath.

I believe if you look at the “Order and Export” tab in the java build path property (Configure Build Path), you will find that the JUnit jar is above the hamcrest.jar. You can move hamcrest above the JUnit jar here and the problem will go away.

  • 重複しているJUnitのHamcrestを削除。

自分は、Eclipseデフォルトのプラグインを削除して、外部から落としてきたJUnitをビルド・パスに設定し直すことで、解決した。ビルド・パスの設定は、以下のエントリを参照。

JUnitのインストールとEclipseでの使い方まとめ

image