Error: No URL for ServletContext resource when running Spring integrated test
Error: No URL for ServletContext resource when running Spring integrated test
我是 运行 我的 Spring 控制器的集成测试。测试包括一个配置文件 (view-configuration.xml
),它有 tilesConfigurer
个 bean,我收到错误 No URL for ServletContext resource
。以下是错误跟踪、配置、测试和项目结构:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:101)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:161)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:101)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:331)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:213)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runReflectiveCall(SpringJUnit4ClassRunner.java:290)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:292)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
at org.junit.runners.ParentRunner.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access[=10=]0(ParentRunner.java:53)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
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:176)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tilesConfigurer' defined in class path resource [com/zerosolutions/configuration/view-configuration.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: No URL for ServletContext resource [/WEB-INF/layout/default.xml]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:132)
at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:59)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:250)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91)
... 25 more
Caused by: java.lang.IllegalArgumentException: No URL for ServletContext resource [/WEB-INF/layout/default.xml]
at org.springframework.web.servlet.view.tiles3.SpringWildcardServletTilesApplicationContext.getResources(SpringWildcardServletTilesApplicationContext.java:96)
at org.springframework.web.servlet.view.tiles3.TilesConfigurer$SpringTilesContainerFactory.getSources(TilesConfigurer.java:306)
at org.apache.tiles.factory.BasicTilesContainerFactory.createLocaleDefinitionDao(BasicTilesContainerFactory.java:182)
at org.apache.tiles.factory.BasicTilesContainerFactory.createDefinitionsFactory(BasicTilesContainerFactory.java:137)
at org.springframework.web.servlet.view.tiles3.TilesConfigurer$SpringTilesContainerFactory.createDefinitionsFactory(TilesConfigurer.java:354)
at org.apache.tiles.factory.BasicTilesContainerFactory.createContainer(BasicTilesContainerFactory.java:86)
at org.springframework.web.servlet.view.tiles3.TilesConfigurer$SpringTilesContainerFactory.createContainer(TilesConfigurer.java:297)
at org.apache.tiles.startup.AbstractTilesInitializer.createContainer(AbstractTilesInitializer.java:114)
at org.apache.tiles.startup.AbstractTilesInitializer.initialize(AbstractTilesInitializer.java:64)
at org.springframework.web.servlet.view.tiles3.TilesConfigurer.afterPropertiesSet(TilesConfigurer.java:271)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 40 more
Caused by: java.io.FileNotFoundException: ServletContext resource [/WEB-INF/layout/default.xml] cannot be resolved to URL because it does not exist
at org.springframework.web.context.support.ServletContextResource.getURL(ServletContextResource.java:156)
at org.springframework.web.servlet.view.tiles3.SpringWildcardServletTilesApplicationContext.getResources(SpringWildcardServletTilesApplicationContext.java:91)
... 51 more
查看-configuration.xml:
<mvc:resources location="/resource/" mapping="/static/**"></mvc:resources>
<bean id="tilesViewResolver"
class="org.springframework.web.servlet.view.tiles3.TilesViewResolver">
</bean>
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/layout/default.xml</value>
</list>
</property>
</bean>
测试
@RunWith(value=SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "file:WebContent/WEB-INF/dispatcher-servlet.xml",
"classpath:com/zerosolutions/configuration/service-configuration.xml",
"classpath:com/zerosolutions/configuration/security-configuration.xml",
"classpath:com/zerosolutions/test/datasource_test.xml",
"classpath:com/zerosolutions/configuration/view-configuration.xml"})
public class TestingFrontController {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp(){
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void getLoginSignupPage() throws Exception{
mockMvc.perform(get("/login"))
.andExpect(status().isOk())
.andExpect(forwardedUrl("login"));
}
}
项目结构:
为什么找不到资源?
当 Spring TestContext Framework 为用 @WebAppConfiguration
注释的测试加载 ApplicationContext
时,它实际上加载了需要 ServletContext
的 WebApplicationContext
。在集成测试中,Spring 为您创建一个 MockServletContext
,resourceBasePath
设置为 @WebAppConfiguration
注释中 value
属性的值。
如果您阅读了 @WebAppConfiguration
的 Javadoc,您会注意到默认路径是 src/main/webapp
。
因此,答案是您不遵循 WAR 项目的 Maven 约定。换句话说,src/main/webapp
不是您网页内容的根目录。相反,在您的项目中它是 WebContent
.
如下更改 @WebAppConfiguration
的声明应该可以解决您的问题。
@WebAppConfiguration("WebContent")
此致,
Sam(Spring TestContext Framework 的作者)
我尝试了山姆提供的解决方案。它对我不起作用。
所以我尝试将 tiles.xml 放入资源文件夹,因为我知道它只需要能够在上下文中找到。
我知道这不是解决问题的正确方法。但它对我有用。
@Bean
public TilesConfigurer tilesConfigurer() {
final TilesConfigurer configurer = new TilesConfigurer();
configurer.setDefinitions("classpath:tiles.xml");
configurer.setCheckRefresh(true);
return configurer;
}
当您没有为所需的 运行 配置设置工作目录时,就会发生这种情况。
如果您使用的是 IntelliJ,您可以将 $MODULE_WORKING_DIR$
指定为 "Working directory:",这应该可以解决您的问题。
我是 运行 我的 Spring 控制器的集成测试。测试包括一个配置文件 (view-configuration.xml
),它有 tilesConfigurer
个 bean,我收到错误 No URL for ServletContext resource
。以下是错误跟踪、配置、测试和项目结构:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:101)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:161)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:101)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:331)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:213)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runReflectiveCall(SpringJUnit4ClassRunner.java:290)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:292)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
at org.junit.runners.ParentRunner.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access[=10=]0(ParentRunner.java:53)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
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:176)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tilesConfigurer' defined in class path resource [com/zerosolutions/configuration/view-configuration.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: No URL for ServletContext resource [/WEB-INF/layout/default.xml]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:132)
at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:59)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:250)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91)
... 25 more
Caused by: java.lang.IllegalArgumentException: No URL for ServletContext resource [/WEB-INF/layout/default.xml]
at org.springframework.web.servlet.view.tiles3.SpringWildcardServletTilesApplicationContext.getResources(SpringWildcardServletTilesApplicationContext.java:96)
at org.springframework.web.servlet.view.tiles3.TilesConfigurer$SpringTilesContainerFactory.getSources(TilesConfigurer.java:306)
at org.apache.tiles.factory.BasicTilesContainerFactory.createLocaleDefinitionDao(BasicTilesContainerFactory.java:182)
at org.apache.tiles.factory.BasicTilesContainerFactory.createDefinitionsFactory(BasicTilesContainerFactory.java:137)
at org.springframework.web.servlet.view.tiles3.TilesConfigurer$SpringTilesContainerFactory.createDefinitionsFactory(TilesConfigurer.java:354)
at org.apache.tiles.factory.BasicTilesContainerFactory.createContainer(BasicTilesContainerFactory.java:86)
at org.springframework.web.servlet.view.tiles3.TilesConfigurer$SpringTilesContainerFactory.createContainer(TilesConfigurer.java:297)
at org.apache.tiles.startup.AbstractTilesInitializer.createContainer(AbstractTilesInitializer.java:114)
at org.apache.tiles.startup.AbstractTilesInitializer.initialize(AbstractTilesInitializer.java:64)
at org.springframework.web.servlet.view.tiles3.TilesConfigurer.afterPropertiesSet(TilesConfigurer.java:271)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 40 more
Caused by: java.io.FileNotFoundException: ServletContext resource [/WEB-INF/layout/default.xml] cannot be resolved to URL because it does not exist
at org.springframework.web.context.support.ServletContextResource.getURL(ServletContextResource.java:156)
at org.springframework.web.servlet.view.tiles3.SpringWildcardServletTilesApplicationContext.getResources(SpringWildcardServletTilesApplicationContext.java:91)
... 51 more
查看-configuration.xml:
<mvc:resources location="/resource/" mapping="/static/**"></mvc:resources>
<bean id="tilesViewResolver"
class="org.springframework.web.servlet.view.tiles3.TilesViewResolver">
</bean>
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/layout/default.xml</value>
</list>
</property>
</bean>
测试
@RunWith(value=SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "file:WebContent/WEB-INF/dispatcher-servlet.xml",
"classpath:com/zerosolutions/configuration/service-configuration.xml",
"classpath:com/zerosolutions/configuration/security-configuration.xml",
"classpath:com/zerosolutions/test/datasource_test.xml",
"classpath:com/zerosolutions/configuration/view-configuration.xml"})
public class TestingFrontController {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp(){
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void getLoginSignupPage() throws Exception{
mockMvc.perform(get("/login"))
.andExpect(status().isOk())
.andExpect(forwardedUrl("login"));
}
}
项目结构:
为什么找不到资源?
当 Spring TestContext Framework 为用 @WebAppConfiguration
注释的测试加载 ApplicationContext
时,它实际上加载了需要 ServletContext
的 WebApplicationContext
。在集成测试中,Spring 为您创建一个 MockServletContext
,resourceBasePath
设置为 @WebAppConfiguration
注释中 value
属性的值。
如果您阅读了 @WebAppConfiguration
的 Javadoc,您会注意到默认路径是 src/main/webapp
。
因此,答案是您不遵循 WAR 项目的 Maven 约定。换句话说,src/main/webapp
不是您网页内容的根目录。相反,在您的项目中它是 WebContent
.
如下更改 @WebAppConfiguration
的声明应该可以解决您的问题。
@WebAppConfiguration("WebContent")
此致,
Sam(Spring TestContext Framework 的作者)
我尝试了山姆提供的解决方案。它对我不起作用。
所以我尝试将 tiles.xml 放入资源文件夹,因为我知道它只需要能够在上下文中找到。
我知道这不是解决问题的正确方法。但它对我有用。
@Bean
public TilesConfigurer tilesConfigurer() {
final TilesConfigurer configurer = new TilesConfigurer();
configurer.setDefinitions("classpath:tiles.xml");
configurer.setCheckRefresh(true);
return configurer;
}
当您没有为所需的 运行 配置设置工作目录时,就会发生这种情况。
如果您使用的是 IntelliJ,您可以将 $MODULE_WORKING_DIR$
指定为 "Working directory:",这应该可以解决您的问题。