公司这个项目,不是我来配置构建的, 把 spring的配置什么的,和 springmvc的配置没有区分开来,都是在一个配置文件里面,也就是 springmvc 里面。 和我们一般的 配置不一样,我们一般配置都是 配置好 spring 容器的,,然后配置好 springmvc 的分开来。 可是 这个项目不是这样的,,,感觉是有点乱,后期也难维护管理。。。

没办法了。 这个项目,他们是没有 junit 的, 估计他们不喜欢用吧。 可是我是有点喜欢junit 测试的。 所以想自己集成junit ,在写代码的时候,方便自己测试使用。

可是在集成的时候 junit的时候 居然报错了。。。

java.lang.IllegalStateException: Failed to load ApplicationContext
	at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
	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:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	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:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
	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:539)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'initService' defined in file [D:\SVN\rpd-p2p\branches\1.3.1.shortcutpay\rpd-p2p\build\classes\com\moneyP2P\p2p\VSFP\spring\service\InitService.class]: Initialization of bean failed; nested exception is java.lang.ClassCastException: org.springframework.context.support.GenericApplicationContext cannot be cast to org.springframework.web.context.WebApplicationContext
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:628)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
	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)
	... 25 more
Caused by: java.lang.ClassCastException: org.springframework.context.support.GenericApplicationContext cannot be cast to org.springframework.web.context.WebApplicationContext
	at com.moneyP2P.p2p.VSFP.spring.service.InitService.setApplicationContext(InitService.java:251)
	at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:117)
	at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:92)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:396)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1505)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
	... 39 more

什么意思啊。。。? 百度一下,,,发现这样的问题实在是太少了。。。 使用网上的办法发现也不行啊。 我一点点看的时候,发现是在 某个 service 类初始化的时候,报错了。 这个 service implements ApplicationContextAware 这类。 按理来说,应该可以获取到啊,和 junit测试看起来是没有问题的。。 继续看报错信息,说是某一些报错了

@Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
    	
        ServletContext application = ((WebApplicationContext) applicationContext)
                .getServletContext();

        application.setAttribute(
                WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
                applicationContext);
        columnServic.queryAllTopics(application);
        application.setAttribute("application_link", linkService.query());
        application.setAttribute("application_banner", bannerService.query());
        //页面底部信息
        application.setAttribute("footer", footerservice.queryFooter());
        //页面系统信息
        application.setAttribute("sysconfig", syscfgService.getSysConfig());
        initEnumStatus(application);
        initSetSafetyQuestion(application);
        initSetServiceUser(application);
        
        
    }

看到了? 这里 是 WebApplicationContext , 和web相关要拿到 servlet 容器相关的。 我们一般都是 直接获取 ApplicationContext 就可以了。 而我的junit 测试,只是想 测试 spring的 service 而已,并不是 controller 类。 但是这里是 要获取 WebApplicationContext 类的,所以执行 junit 初始化的时候获取不到就报错了。 并且也试过在 junit 测试的之前,构建 WebApplicationContext ,结果也是不行的。

因此只能 使用 junit的 web测试 方式来了,这样应该就可以了。 构建来了之后果然可以了。 下面是我的 junit spring mvc 测试类

package com.mytest.junit;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import com.moneyP2P.p2p.VSFP.spring.controller.test.MyTestController;
import com.moneyP2P.p2p.VSFP.spring.service.UserBaseInfoService;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = "classpath*:config/main/spring-mvc.xml")
// 默认不回滚, 如果需要 回滚,请自己 在方法 加上 回滚, @Rollback(true) 或者是 defaultRollback = true
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
// extends AbstractTransactionalJUnit4SpringContextTests
public class MyJunitTest extends AbstractTransactionalJUnit4SpringContextTests {

	// @Autowired
	// private WebApplicationContext wac;

	@Autowired
	private MyTestController myTestController;

	private MockMvc mockMvc;

	@Autowired
	private UserBaseInfoService userBaseInfoService;

	@Before
	public void setup() {
		// 模拟web必须有这个 构建代码否则报错
		mockMvc = MockMvcBuilders.standaloneSetup(myTestController).build();
	}

	@Test
	public void test() {

		System.out.println("==");
		System.out.println(userBaseInfoService.queryUserById(113L).getUserName());

	}
}

这样我们写 test 方法的时候,直接就获取 spring 的bean 来测试了,或者说想 mockMVC 使用 controller 来测试 也是可以的。

参考 http://andy-ghg.iteye.com/blog/1772215

@RunWith(SpringJUnit4ClassRunner.class)  
@WebAppConfiguration  
@ContextConfiguration(locations = { "classpath:applicationContext-core.xml",  
        "classpath:applicationContext-servlet.xml" })  
public class TestController {  
  
    @Autowired  
    private WebApplicationContext wac;  
  
    @Autowired  
    private SYSUserController userController;//你要测试的Controller  
  
    private MockMvc mockMvc;  
  
    @Before  
    public void setup() {  
        mockMvc = MockMvcBuilders.standaloneSetup(userController).build();  
    }  
  
    @Test  
    public void testFindPageUsers() throws Exception {  
        ResultActions ra = this.mockMvc.perform(MockMvcRequestBuilders  
                .post("/sysconfig/user/findPageUsers")  
                .accept(MediaType.APPLICATION_JSON).param("page", "1")  
                .param("limit", "10"));  
        MvcResult mr = ra.andReturn();  
        String result = mr.getResponse().getContentAsString();  
        log.info(result);  
    }  
  
}