在使用Junit的测试中配置Application
新建maven项目,添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
新建Account类
public class Account {
private long id;
private String ownerName;
private double balance;
private Date accessTime;
public long getId() {
return id;
}
public String getOwnerName() {
return ownerName;
}
public double getBalance() {
return balance;
}
public Date getAccessTime() {
return accessTime;
}
public void setOwnerName(String ownerName) {
this.ownerName = ownerName;
}
public void setId(long id) {
this.id = id;
}
public void setBalance(double balance) {
this.balance = balance;
}
public void setAccessTime(Date accessTime) {
this.accessTime = accessTime;
}
}
新建AccountDao接口及其实现
public class AccountDaoImpl implements AccountDao {
private Map<Long,Account> accountMap = new HashMap<Long, Account>();
{
Account account1 = new Account();
account1.setId(100L);
account1.setOwnerName("John");
account1.setBalance(100d);
account1.setAccessTime(new Date());
Account account2 = new Account();
account2.setId(101L);
account2.setOwnerName("Joe");
account2.setBalance(50d);
account2.setAccessTime(new Date());
accountMap.put(account1.getId(),account1);
accountMap.put(account2.getId(),account2);
}
public Account find(long id){
return accountMap.get(id);
}
public void delete(long id){
accountMap.remove(id);
}
public void insert(Account account){
accountMap.put(account.getId(),account);
}
public void update(Account account){
accountMap.put(account.getId(),account);
}
}
新建AccountService接口及其实现
public class AccountServiceImpl implements AccountService {
AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transferMoney(long sourceId, long targetId, double money){
Account sourceAccount = accountDao.find(sourceId);
Account targetAccount = accountDao.find(targetId);
sourceAccount.setBalance(sourceAccount.getBalance() - money);
targetAccount.setBalance(targetAccount.getBalance() + money);
accountDao.update(sourceAccount);
accountDao.update(targetAccount);
}
public void depositMoney(long id,double money){
Account account = accountDao.find(id);
account.setBalance(account.getBalance() + money);
accountDao.update(account);
}
public Account getAccount(long id){
return accountDao.find(id);
}
}
在main/java/resources中添加applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd">
<bean id="accountService" class="service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<bean id="accountDao" class="dao.impl.AccountDaoImpl"/>
</beans>
在src/test/java中新建AccountIntegrationTests类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext.xml")
public class AccountIntegrationTests {
@Autowired
private AccountService accountService;
@Test
public void accountServiceShouldBeInjected(){
Assert.assertNotNull(accountService);
}
}
运行Junit进行测试
示例说明
当运行测试代码时,Spring能够自动创建和管理ApplicationContext.
首先指定可以运行测试类的JunitRunner类。所以用@RunnerWith注解。本例使用SpringJUnit4ClassRunner类作为RunWith类。
在Test类中用@Test注解来表示可以测试的方法。
使用ApplicationContext.xml来配置accountDao和accountService这两个Bean.
除了使用xml配置文件,还可以使用配置类来配置Bean
继承上下文配置
新建Foo类和Bar类
public class Foo {
}
public class Bar {
}
在classpath路径下新建baseContext.xml和subContext.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd">
<bean id="foo" class="ov.Foo"/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd">
<bean id="bar" class="ov.Bar"/>
</beans>
新建BaseTest测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/baseContext.xml")
public class BaseTest {
@Autowired
protected Foo foo;
}
新建SubTest测试类,继承子BaseTest类
@ContextConfiguration("classpath:/subContext.xml")
public class SubTest extends BaseTest{
@Autowired
private Bar bar;
@Test
public void dependenciesShouldBeAvailable(){
Assert.assertNotNull(foo);
Assert.assertNotNull(bar);
}
}
运行Junit
示例说明
在测试类中继承之后,可以将配置信息以及测试的对象继承。
而Spring TestContext Framwork会自动为测试类配置ApplicationContext.
ApplicationContext缓存
多个测试类指定了完全相同的xml位置或者配置类,那么Spring TestContext FrameWork将只创建一次ApplicationContex实例。该实例存储在一个静态变量中。
在测试中使用事务管理
在测试类上或测试方法上加@Transactional注解,会使类中所有方法或者该方法处在一个事务中,而由于测试的特性,在事务操作后会自动进行回滚。
如果在事务前后想要自动执行某些方法,可以使用@BeforeTransaction和@AfterTransaction注解注解方法。
Mock对象
由于单元测试的理念是只测试单一的对象。而面向对象程序设计难免有依赖项存在,而要测试被测对象还要保证其依赖项也是正确的。然而依赖项的作用有时仅仅是返回特定的数值。所以可以用不同种类的Mock对象来代替这些依赖性,使其可以代替依赖性的作用而正常测试被测对象。