プログラマでありたい

おっさんになっても、プログラマでありつづけたい

S2Junit4でNoClassDefFoundErrorが出たら

 DoltengでS2JDBCオンリーやS2DAOオンリーでプロジェクト作成した場合に、S2TestCaseを実行しようとするとNoClassDefFoundErrorが出ると思います。原因はS2TastCaseが、ServletAPIを必要としているからです。
 対処策としては、pom.xmlにgeronimo-servlet_2.4_specを追加すれば解決します。が、このエラーが出るケースは、画面側とDB側でモジュールを別けたい時だと思います。その時は、pomのscope記述にprovidedと書いておけば、デプロイ時に配布されることはありません。


エラーの内容

java.lang.NoClassDefFoundError: javax/servlet/ServletContext
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
	at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
	at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
	at java.lang.Class.getMethod0(Class.java:2670)
	at java.lang.Class.getMethod(Class.java:1603)
	at org.junit.internal.requests.ClassRequest.hasSuiteMethod(ClassRequest.java:61)
	at org.junit.internal.requests.ClassRequest.getRunnerClass(ClassRequest.java:50)
	at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:28)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:26)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:24)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:40)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:30)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:445)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletContext
	at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
	at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
	... 27 more


対処方法

<dependency>
	<groupId>org.apache.geronimo.specs</groupId>
	<artifactId>geronimo-servlet_2.4_spec</artifactId>
	<version>1.0</version>
	<scope>provided</scope>
</dependency>


スコープの種類 via Maven2のTipsを集めるWiki

scopeには以下の値が設定できる。

compile
デフォルト
provided
デプロイ時には含めたくない場合。例えばservlet-api.jar。
runtime
実行時にのみ必要とする場合。例えばJDBCドライバ。
test
テスト時にのみ必要とする場合。例えばJUnit。
system
providedに似ている。systemPathタグでJarまでのパスを記述する必要がある。例えばJDBC標準拡張やJAASに利用する。


参考:
Seasar-user:5798 Re: Dolteng テストがうまくできません