主要介绍单元测试中获得bean的三种方法,以及各自的优劣。其实跟开发时获得bean方法一样,如下:
a.通过ClassPathXmlApplicationContext得到ApplicationContext,再getBean
b.通过set函数获得bean
c.启用直接对保护类型属性变量进行注入的机制
日常应用中推荐大家使用第二、三中方法。尤其对于bean较多时,使用第三种可以方便省事很多。
所用依赖为junit 3.8.1和spring-test包2.5.6。下面为详细介绍:
1、通过ClassPathXmlApplicationContext得到ApplicationContext,再getBean
单元测试中需要引入bean,最容易想到的办法就是使用spring bean注入的原理,代码如下:
package com..*.*.*.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import com.*.*.*.TestService;
public class TestBean extends AbstractDependencyInjectionSpringContextTests {
@Test
public void testBeanInjection() {
ApplicationContext testContext = new ClassPathXmlApplicationContext("test_services.xml");
TestService testService = (TestService)testContext.getBean("testService");
}
}
先通过ClassPathXmlApplicationContext bean xml得到ApplicationContext,再getBean。
但按照Spring的推荐,在单元测试时不应该依赖于Spring容器,也就是说不应该在单元测试时启动ApplicationContext并从中获取Bean,所以此种方法不推荐。建议大家继续看看下面两种
其中test_services.xml内容如下,下面两种方法一样。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans default-autowire="byName"> <bean id="testService" class="com.*.*.*.TestServiceImpl"> </bean> </beans>
2、通过set函数获得bean
通过getConfigLocations设置bean xml路径
新增setTestService设置函数,对testService赋值
注意testService的类型不限制
package com..*.*.*.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import com.*.*.*.TestService;
public class TestSendEmail extends AbstractDependencyInjectionSpringContextTests {
private TestService testService;
public void setTestService(TestService testService) {
this.testService = testService;
}
/**
* 设置bean xml路径,可以添加多个
*/
protected String[] getConfigLocations() {
return new String[] {"test_services.xml"};
}
@Test
public void testBeanInjection() {
assertTrue(testService != null);
}
}
这种方式的好处在不用手动加载bean xml文件,但每个bean需要一个set函数,当bean较多时需要生成较多set函数
3、启用直接对保护类型属性变量进行注入的机制
通过getConfigLocations设置bean xml路径
新增构造函数,在其中调用setPopulateProtectedVariables(true)设置启用直接对保护类型属性变量进行注入的机制
注意testService为保护型
package com..*.*.*.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import com.*.*.*.TestService;
public class TestBean extends AbstractDependencyInjectionSpringContextTests {
protected TestService testService;
public TestBean(){
// 启用直接对保护类型属性变量进行注入的机制
this.setPopulateProtectedVariables(true);
}
/**
* 设置bean xml路径,可以添加多个
*/
protected String[] getConfigLocations() {
return new String[] {"test_services.xml"};
}
@Test
public void testBeanInjection() {
assertTrue(testService != null);
}
}
这种方式的好处在不用手动加载bean xml文件,也不用再写set函数 ,但需要一个构造函数并在其中启用直接对保护类型属性变量进行注入的机制
其他:
程序中依赖了spring-test的包,需要在pom中添加依赖如下
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>2.5.6</version> </dependency>
参考:http://mvnrepository.com/artifact/org.springframework/spring-test/2.5