J'utilise Sping MVC dans mon application et j'écris des scénarios de test JUnit pour un DAO. Lorsque je lance le test, le message d'erreur suivant s'affiche: Java.lang.ClassNotFoundException: javax.servlet.ServletContext
.
Dans le stacktrace, je vois que cette erreur est provoquée pendant getApplicationContext
. Dans ma applicationContext
, je n'ai défini aucun servlet. Le mappage de servlet est effectué uniquement dans web.xml
. Je ne comprends donc pas pourquoi cette erreur me vient
Voici mon applicationContext.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"
xmlns:tx="http://www.springframework.org/schema/tx">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/testdb"/>
<property name="user" value="username"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.url">jdbc:mysql://localhost:3306/myWorld_test</prop>
<prop key="hibernate.connection.username">username</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.myprojects.pojos</value>
</list>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<context:component-scan base-package="com.myprojects"/>
<context:annotation-config/>
<mvc:annotation-driven/>
</beans>
Voici le stacktrace:
Java.lang.NoClassDefFoundError: javax/servlet/ServletContext
at Java.lang.Class.getDeclaredMethods0(Native Method)
at Java.lang.Class.privateGetDeclaredMethods(Class.Java:2521)
at Java.lang.Class.getDeclaredMethods(Class.Java:1845)
at org.springframework.core.type.StandardAnnotationMetadata.hasAnnotatedMethods(StandardAnnotationMetadata.Java:161)
at org.springframework.context.annotation.ConfigurationClassUtils.isLiteConfigurationCandidate(ConfigurationClassUtils.Java:106)
at org.springframework.context.annotation.ConfigurationClassUtils.checkConfigurationClassCandidate(ConfigurationClassUtils.Java:88)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.Java:253)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.Java:223)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.Java:630)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:461)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.Java:120)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.Java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.Java:100)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.Java:248)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.Java:64)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.Java:91)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.Java:122)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.Java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.Java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.Java:312)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.Java:211)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.Java:288)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.Java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.Java:284)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.Java:231)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.Java:88)
at org.junit.runners.ParentRunner$3.run(ParentRunner.Java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.Java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.Java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.Java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.Java:229)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.Java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.Java:61)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.Java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.Java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.Java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.Java:174)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.Java:80)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.Java:47)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.Java:69)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.Java:49)
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:606)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.Java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.Java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.Java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.Java:93)
at com.Sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.Java:103)
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:606)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.Java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.Java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.Java:355)
at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.Java:66)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1145)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:615)
at Java.lang.Thread.run(Thread.Java:724)
Caused by: Java.lang.ClassNotFoundException: javax.servlet.ServletContext
at Java.net.URLClassLoader$1.run(URLClassLoader.Java:366)
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:424)
at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:308)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:357)
... 62 more
Classe de test:
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class UserServiceTest {
@Autowired
private UserService service;
public UserServiceTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
}
Même avant d'écrire une méthode de test, j'ai eu cette erreur.
Vous avez un seul fichier xml pour votre ApplicationContext
. Dans ce fichier, il y a une balise <mvc:annotation-driven />
. Cette balise charge différentes ressources Web (résolveurs de vue, mappages de gestionnaires, etc.) et nécessite donc que l’API Servlet soit disponible.
Vous devriez déjà avoir l’API Servlet sur votre chemin de classe comme dépendance fournie dans maven.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
En plus de cela, vous voudrez peut-être supprimer la balise <mvc:annotation-driven />
et la placer dans un fichier de configuration séparé. C'est aussi une balise qui devrait (en général) être chargée par la variable DispatcherServlet
. (Je suppose qu'applicationContext.xml est, par défaut, chargé par la variable ContextLoaderListener
).
1.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
2.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/spring-mvc.xml")
@WebAppConfiguration
Ces conseils m'ont aidé.
Maven n'a pas pu charger javax.servlet-api
dans la version 3.0.1: /
Cette dépendance a résolu mon problème:
<dependency>
<groupId>org.Apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_3.0_spec</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
Il contient toutes les classes de javax.servlet.
Pour moi, j'ai ajouté le @WebAppConfiguration et cela a résolu mon problème.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestConfig.class})
@WebAppConfiguration
public class WebAppTest {
@Test
public void test() throws Exception {
}
}