我在 spring-mvc-test 和以下测试类中遇到了一个神秘的问题:
import static com.mycompany.testUtils.SecurityRequestPostProcessors.userDetailsService;
import static org.mockito.Mockito.mock;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import com.mycompany.services.AccountService;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "classpath*:spring-config-*.xml",
"file:src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml" })
public class SecurityTests {
@Autowired
private AccountService accountService;
@Autowired
private WebApplicationContext wac;
@Autowired
private FilterChainProxy springSecurityFilterChain;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = webAppContextSetup(wac).addFilters(springSecurityFilterChain)
.build();
}
@Test
public void test() throws Exception {
mockMvc.perform(
get("/welcome").with(userDetailsService("dummy@mycompany.com")))
.andExpect(status().isForbidden());
}
@Configuration
public static class testConfiguration {
@Bean
public AccountService accountService() {
return mock(AccountService.class);
}
}
}
这是mvc-dispatcher-servlet.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<!-- <context:annotation-config/> -->
<mvc:annotation-driven />
<context:component-scan base-package="com.mycompany" />
<!-- Internationalization -->
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="fr" />
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<mvc:interceptors>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
</mvc:interceptors>
</beans>
这是最后的堆栈跟踪:
10:51:35.639 [main] ERROR o.s.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@fb76c8] to prepare test instance [com.mycompany.ui.controller.security.SecurityTests@1337d64]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99) ~[spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:122) ~[spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:105) ~[spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:74) ~[spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:312) ~[spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211) [spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288) [spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) [junit-4.10.jar:na]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284) [spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) [spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88) [spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) [junit-4.10.jar:na]
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) [junit-4.10.jar:na]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) [junit-4.10.jar:na]
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) [junit-4.10.jar:na]
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) [junit-4.10.jar:na]
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) [spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.junit.runners.ParentRunner.run(ParentRunner.java:300) [junit-4.10.jar:na]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) [spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) [.cp/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1007) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:953) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:487) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) ~[spring-context-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) ~[spring-context-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:128) ~[spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:60) ~[spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100) ~[spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:248) ~[spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64) ~[spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91) ~[spring-test-3.2.3.RELEASE.jar:3.2.3.RELEASE]
... 25 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1000) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
... 41 common frames omitted
Caused by: java.lang.NullPointerException: null
at java.nio.charset.Charset.put(Charset.java:550) ~[na:1.7.0_03]
at java.nio.charset.Charset.access$300(Charset.java:276) ~[na:1.7.0_03]
at java.nio.charset.Charset$4.run(Charset.java:593) ~[na:1.7.0_03]
at java.nio.charset.Charset$4.run(Charset.java:585) ~[na:1.7.0_03]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_03]
at java.nio.charset.Charset.availableCharsets(Charset.java:584) ~[na:1.7.0_03]
at org.springframework.http.converter.StringHttpMessageConverter.<init>(StringHttpMessageConverter.java:66) ~[spring-web-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.http.converter.StringHttpMessageConverter.<init>(StringHttpMessageConverter.java:56) ~[spring-web-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.<init>(RequestMappingHandlerAdapter.java:177) ~[spring-webmvc-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.7.0_03]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) ~[na:1.7.0_03]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.7.0_03]
at java.lang.reflect.Constructor.newInstance(Constructor.java:525) ~[na:1.7.0_03]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148) ~[spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
... 43 common frames omitted
10:51:35.651 [main] DEBUG o.s.t.c.s.DirtiesContextTestExecutionListener - After test class: context [[TestContext@165e583 testClass = SecurityTests, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@1e6cb2a testClass = SecurityTests, locations = '{classpath*:spring-config-*.xml, file:src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]]]], dirtiesContext [false].
请注意,该应用程序在浏览器中运行良好。只有在运行上述测试类时才会出现该问题。