转自:http://www.programgo.com/article/88183221961/
TestContext 测试框架的核心由 org.springframework.test.context 包中三个类组成,分别是 TestContext 和 TestContextManager 类以及 TestExecutionListener 接口。
每次测试都会创建TestContextManager。TestContextManager管理了一个TestContext, 它负责持有当前测试的上下文。TestContextManager还负责在测试执行过程中更新TestContext的状态并代理到TestExecutionListener, 它用来监测测试实际的执行(如提供依赖注入、管理事务等等)
TestContext
TestContext:封装测试执行的上下文,与当前使用的测试框架无关。
TestContextManager
TestContextManager:Spring TestContext Framework的主入口点, 负责管理单独的TestContext并在定义好的执行点上向所有注册的TestExecutionListener发出事件通知: 测试实例的准备,先于特定的测试框架的前置方法,迟于后置方法。
TestExecutionListener
TestExecutionListener:定义了一个监听器API与TestContextManager发布的测试执行事件进行交互, 而该监听器就是注册到这个TestContextManager上的。
Spring提供了TestExecutionListener的三个实现, 他们都是使用默认值进行配置的(通过@TestExecutionListeners注解): DependencyInjectionTestExecutionListener、DirtiesContextTestExecutionListener及TransactionalTestExecutionListener, 他们对测试实例提供了依赖注入支持,处理@DirtiesContext注解,并分别使用默认的回滚语义对测试提供事务支持。
DependencyInjectionTestExecutionListener:该监听器提供了自动注入的功能,它负责解析测试用例中 @Autowried 注解并完成自动注入;
DirtiesContextTestExecutionListener:一般情况下测试方法并不会对 Spring 容器上下文造成破坏(改变 Bean 的配置信息等),如果某个测试方法确实会破坏 Spring 容器上下文,你可以显式地为该测试方法添加 @DirtiesContext 注解,以便 Spring TestContext 在测试该方法后刷新 Spring 容器的上下文,而 DirtiesContextTestExecutionListener 监听器的工作就是解析 @DirtiesContext 注解;
TransactionalTestExecutionListener:它负责解析 @Transaction、@NotTransactional 以及 @Rollback 等事务注解的注解。@Transaction 注解让测试方法工作于事务环境中,不过在测试方法返回前事务会被回滚。你可以使用 @Rollback(false) 让测试方法返回前提交事务。而 @NotTransactional 注解则让测试方法不工作于事务环境中。此外,你还可以使用类或方法级别的 @TransactionConfiguration 注解改变事务管理策略
下面是各个注解的解释:
@TestExecutionListeners:用来注册TestExecutionListener
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class})
@ContextConfiguration:用来指定加载的Spring配置文件的位置,会加载默认配置文件
1. locations属性
@ContextConfiguration不带locations属性,GenericXmlContextLoader会基于测试类的名字产生一个默认的位置.
如果类名叫做com.example.MyTest,那么GenericXmlContextLoader就会从"classpath:/com/example/MyTest-context.xml"加载应用上下文。
@ContextConfiguration 若带有locations属性
@ContextConfiguration(locations= { "spring-service.xml","spring-service1.xml" }) 会去加载指定文件
2. inheritLocations属性
@ContextConfiguration的inheritLocations属性 (是否继承父类的locations),默认为true
@ContextConfiguration(locations={"/base-context.xml"})
@ContextConfiguration(locations={"/extended-context.xml"})
为true时,会将/base-context.xml, /extended-context.xml 合并加载,若有重载的bean为子类为准
为false时,会屏蔽掉父类的资源位置
@RunWith 注解指定测试用例的运行器
@RunWith(SpringJUnit4ClassRunner.class)
SpringJUnit4ClassRunner:Spring TestContext 框架提供了扩展于 org.junit.internal.runners.JUnit4ClassRunner 的 SpringJUnit4ClassRunner 运行器,它负责总装 Spring TestContext 测试框架并将其统一到 JUnit 4.4 框架中。
它负责无缝地将 TestContext 测试框架移花接木到 JUnit 4.4 测试框架中,它是 Spring TestContext 可以运行起来的根本所在
示例:
package com.xxx.muce.calctemplate.dao; import com.github.springtestdbunit.DbUnitTestExecutionListener; import com.github.springtestdbunit.annotation.DatabaseSetup; import com.xxx.muce.calctemplate.model.Param; 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.TestExecutionListeners; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import org.springframework.test.context.transaction.TransactionalTestExecutionListener; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"/applicationContext-calctemplate-dao.xml", "/applicationContext-calctemplate-resources.xml"}) @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class, DbUnitTestExecutionListener.class }) @DatabaseSetup("classpath:/allTable.xml") public class ParamDaoTest { @Autowired private ParamDao paramDao; @Test public void testGetParamListByStepIds() throws Exception { List<String> paramNameList = new ArrayList<>(Arrays.asList("param_text_output", "param_label_intro", "param_textarea_hivesql")); List<Param> paramList = paramDao.getParamListByStepIds("1"); assertEquals(3, paramList.size()); for (Param param : paramList) { assertTrue(paramNameList.contains(param.getName())); } } @Test public void testGetParamListByTemplateId() throws Exception { List<String> paramNameList = new ArrayList<>(Arrays.asList("param_text_output", "param_label_intro", "param_textarea_hivesql")); List<Param> paramList = paramDao.getParamListByTemplateId(1); assertEquals(3, paramList.size()); for (Param param : paramList) { assertTrue(paramNameList.contains(param.getName())); } } }