Constructor threw exception; nested exception is j

2019-02-17 06:34发布

问题:

I am trying to setup 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 pom.xml but didn't work. any idea?

    <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`

Ok, Updated based on the comments, so I changed the scope to compile then it seems pass 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>

回答1:

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 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.



回答2:

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

Project -> Properties ->Deployment Assembly -> Add -> java Build Path Enteries -> Ivy -> Finish

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.