7

I am trying to set up the JUnit test with the MockMVC.

From this link - "either must not use the Servlet API or you need to provide it on the classpath".

I added the following to file pom.xml, but it didn't work. What should I do?

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>

Here is the trace:

org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.test.context.web.WebDelegatingSmartContextLoader]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: javax/servlet/ServletContext
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:105)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:130)
    at org.springframework.test.context.ContextLoaderUtils.resolveContextLoader(ContextLoaderUtils.java:118)
    at org.springframework.test.context.ContextLoaderUtils.buildMergedContextConfiguration(ContextLoaderUtils.java:594)
    at org.springframework.test.context.ContextLoaderUtils.buildMergedContextConfiguration(ContextLoaderUtils.java:560)
    at org.springframework.test.context.TestContext.<init>(TestContext.java:99)
    at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:117)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTestContextManager(SpringJUnit4ClassRunner.java:119)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<init>(SpringJUnit4ClassRunner.java:108)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
Caused by: java.lang.NoClassDefFoundError: javax/servlet/ServletContext
    at org.springframework.test.context.web.WebDelegatingSmartContextLoader.<init>(WebDelegatingSmartContextLoader.java:36)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
    ... 22 more
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)
    ... 28 more`enter code here`

Based on the comments, I changed the scope to compile, and then it seems past the issue of class not found!

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>compile</scope>
</dependency>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jaxox
  • 960
  • 4
  • 14
  • 25
  • check if the servlet dependency is being downloaded. Try downloading all the dependencies into a separate folder with `mvn dependency:copy-dependencies -Dclassifer=directory` and see if they all make it – bhowden Jun 24 '14 at 18:29

2 Answers2

7

It is a common issue. As Aniket Thakur said, the container will provide all Java Servlet classes at runtime. But during the tests you need a JAR file to provide them.

The dependency you added to your POM is only the API: it declares everything but contains no implementation. So it will not help. Anyway, you declare it as "provided" which says to Maven "don't worry, I know it will be on classpath".

You have to add a dependency that bring the implementation of all Java EE classes in test scope. In my projects I use GlassFish even if I later use Tomcat as a Servlet container, but I once found the dependency googling for the same problem:

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.servlet</artifactId>
    <version>3.0</version>
    <scope>test</scope>
</dependency>

It should solve your NoClassDefFoundError problem.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
4

Class is not found at runtime, but it is available at compile time. You need to add the corresponding JAR file so that it can be found at runtime. I generally use Ivy and in Eclipse I do:

Menu ProjectPropertiesDeployment AssemblyAddJava Build Path EntriesIvyFinish

There must be something similar for Maven as well.

Also you need javax.servlet-api only during compile time as the container you are using to run the server will provide the actual APIs at runtime.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Aniket Thakur
  • 66,731
  • 38
  • 279
  • 289