jMockのエラーにはまる

久しぶりにEclipseを起動して、jMockのプロジェクトを作ってモックの動作を試してみる。動作環境は下記の通り。

下記のサイトを参考にしてプロジェクトを作成した。

ライブラリには下記を使った。

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

テストを実行させてみると、下記の例外が発生してしまう。テストが上手く実行出来ていない。

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:807)
	at java.lang.ClassLoader.preDefineClass(ClassLoader.java:488)
	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:626)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
	at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
	at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
	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.doSomething(Unknown Source)
	at bar.FooTest$1.<init>(FooTest.java:33)
	at bar.FooTest.testSome(FooTest.java:32)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	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:96)
	at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:59)
	at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:52)
	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:50)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
	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)

調べたところ、EclipseJUnitプラグインに含まれるHamcrestと、jMockが使うHamcrestのバージョンが異なっているのが原因らしいと分かった。

I encountered this problem again today. It seems that Eclipse Galileo bundles JUnit 4.5, which in turn bundles Hamcrest Core 1.1, which does not contain org.hamcrest.TypeSafeMatcher.

JMock 2.5.1, however, bundles Hamcrest 1.1, with TypeSafeMatcher. The Eclipse JUnit 4.5 distribution contains signed JARs, and hence the exception.

The solution is to ensure that any dependencies on JMock JARs occur before dependencies on JUnit in every plug-in. That way, Hamcrest is loaded from JMock, not from JUnit.

http://old.nabble.com/SecurityException-when-using-ClassImposteriser-td24304562.html

アドバイスに従ってプロジェクトの設定を変更してJUnit4を読み込む順番を最後にしたところ、無事にテストが動作するようになった。