Spring TestContext 测试框架体系结构
TestContext 核心类、支持类以及注解类
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 注解指定测试用例的运行器
@RunWith(SpringJUnit4ClassRunner.class)
SpringJUnit4ClassRunner
Spring TestContext 框架提供了扩展于 org.junit.internal.runners.JUnit4ClassRunner 的 SpringJUnit4ClassRunner 运行器,它负责总装 Spring TestContext 测试框架并将其统一到 JUnit 4.4 框架中。
它负责无缝地将 TestContext 测试框架移花接木到 JUnit 4.4 测试框架中,它是 Spring TestContext 可以运行起来的根本所在
持有TestContextManager的引用
privatefinal TestContextManager testContextManager;
ContextCache
缓存ApplicationContext
ContextLoader
Interface 加载context接口
GenericXmlContextLoader
为默认的ContextLoader
ApplicationContextAware
自动加载ApplicationContext
AbstractJUnit4SpringContextTests
对集成了Spring TestContext Framework与JUnit 4.4环境中的ApplicationContext
测试支持的基本测试类进行了抽取。
当你继承AbstractJUnit4SpringContextTests
时,你就可以访问到protected
的成员变量:
o applicationContext
:使用它进行显式的bean查找或者测试整个上下文的状态。
AbstractTransactionalJUnit4SpringContextTests
对为JDBC访问增加便捷功能的AbstractJUnit4SpringContextTests
的事务扩展进行抽象。 需要在ApplicationContext
中定义一个javax.sql.DataSource
bean和一个PlatformTransactionManager
bean。
当你继承AbstractTransactionalJUnit4SpringContextTests
类时,你就可以访问到下列protected
的成员变量:
o applicationContext
:继承自父类AbstractJUnit4SpringContextTests
。 使用它执行bean的查找或者测试整个上下文的状态
o simpleJdbcTemplate
:当通过查询来确认状态时非常有用。例如,应用代码要创建一个对象, 然后使用ORM工具将其持久化,这时你想在测试代码执行前后对其进行查询,以确定数据是否插入到数据库中。 (Spring会保证该查询运行在相同事务内。)你需要告诉你的ORM工具‘flush’其改变以正确完成任务,例如, 使用HibernateSession
接口的flush()
方法。
提示
这些类仅仅为扩展提供了方便。 如果你不想将你的测试类绑定到Spring的类上 - 例如,如果你要直接扩展你想测试的类 - 只需要通过@RunWith(SpringJUnit4ClassRunner.class)
、 @ContextConfiguration
、@TestExecutionListeners
等注解来配置你自己的测试类就可以了。
常用注解
Spring框架在org.springframework.test.annotation
包中提供了常用的Spring特定的注解集,如果你在Java5或以上版本开发,可以在测试中使用它。
@IfProfileValue
提示一下,注解测试只针对特定的测试环境。 如果配置的ProfileValueSource
类返回对应的提供者的名称值
, 这个测试就可以启动。这个注解可以应用到一个类或者单独的方法。
@IfProfileValue(name="java.vendor", value="Sun Microsystems Inc.")
publicvoid testJoin() {
System.out.println(System.getProperty("java.vendor"));
}
@ProfileValueSourceConfiguration
类级别注解用来指定当通过@IfProfileValue
注解获取已配置的profile值时使用何种ProfileValueSource
。 如果@ProfileValueSourceConfiguration
没有在测试中声明,将默认使用SystemProfileValueSource
@ProfileValueSourceConfiguration(CustomProfileValueSource.class)
SystemProfileValueSource中的代码
public String get(String key) {
Assert.hasText(key, "'key' must not be empty");
return System.getProperty(key);
}
@DirtiesContext
在测试方法上出现这个注解时,表明底层Spring容器在该方法的执行中被“污染”,从而必须在方法执行结束后重新创建(无论该测试是否通过)。
@DirtiesContext
publicvoid testJoinC() {
Assert.assertEquals(true, false);
}
@ExpectedException
表明被注解方法预期在执行中抛出一个异常。预期异常的类型在注解中给定。如果该异常的实例在测试方法执行中被抛出, 则测试通过。同样的如果该异常实例没有在测试方法执行时抛出,则测试失败。
@ExpectedException(MemberServiceException.class)
publicvoid testChangePassword() {}
协同使用Spring的@ExpectedException
注解与JUnit 4的@Test(expected=...)
会导致一个不可避免的冲突。 因此当与JUnit 4集成时,开发者必须选择其中一个,在这种情况下建议使用显式的JUnit 4配置。
@Timed
表明被注解的测试方法必须在规定的时间区间内执行完成(以毫秒记)。如果测试执行时间超过了规定的时间区间,测试就失败了。
注意该时间区间包括测试方法本身的执行,任何重复测试(参见 @Repeat
),还有任何测试fixture的set up或tear down时间。
@Timed(millis=100)
publicvoid testPersonByVerifiedMobile(){}
Spring的@Timed
注解与JUnit 4的@Test(timeout=...)
支持具有不同的语义。 特别地,鉴于JUnit 4处理测试执行超时(如通过在一个单独的线程
中执行测试方法)的方式, 我们不可能在一个事务上下文中的测试方法上使用JUnit的@Test(timeout=...)
配置。因此, 如果你想将一个测试方法配置成计时且具事务性的, 你就必须联合使用Spring的@Timed
及@Transactional
注解。 还值得注意的是@Test(timeout=...)
只管测试方法本身执行的次数,如果超出的话立刻就会失败; 然而,@Timed
关注的是测试执行的总时间(包括建立和销毁操作以及重复),并且不会令测试失败。
@Repeat
表明被注解的测试方法必须重复执行。执行的次数在注解中声明。
注意重复执行范围包括包括测试方法本身的执行,以及任何测试fixture的set up或tear down。
@Test
@Timed(millis=100)
@Repeat(10)
publicvoid testPersonByVerifiedMobile()
@Rollback
表明被注解方法的事务在完成后是否需要被回滚。 如果true
,事务将被回滚,否则事务将被提交。 使用@Rollback
接口来在类级别覆写配置的默认回滚标志。
@Rollback(false)
publicvoid testPersonByVerifiedMobile()
@Transactional
出现该注解表明测试方法必须在事务中执行。
@NotTransactional
出现该注解表明测试方法必须不在事务中执行。
@NotTransactional
publicvoid testPersonByVerifiedMobile()
@Autowired
按类型注入(可以写在属性上也可以写在setter上)
@Autowired
Join join11;
@Autowired
publicvoid setJoin11(Join join11) {
this.join11 = join11;
}
@Resource
JSR 250中注解. 与@Autowired
类似
@Resource
publicvoid setJoin(Join join) {
this.join = join;
}
@Resource
Join join;
@Autowired 与@Resource 都可以用来装配bean. 都可以写在字段上,或写在set方法上
@Autowired (srping提供的) 默认按类型装配
@Resource ( j2ee提供的 ) 默认按名称装配,当找不到(不写name属性)名称匹配的bean再按类型装配.
可以通过@Resource(name="beanName") 指定被注入的bean的名称, 要是指定了name属性, 就用 字段名 去做name属性值,一般不用写name属性.
@Resource(name="beanName")指定了name属性,按名称注入但没找到bean, 就不会再按类型装配了.
推荐@Autowired 与@Resource作用有字段上, 就不用写set方法了,也不要写@Resource(name="beanName").
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD})
public@interfaceAutowired
@Qualifier
在需要更多控制的时候,任何autowired的域、构造参数、或者方法参数可以进一步加注@Qualifier注解。qualifier可以包含一个字符串值,在这种情况下,Spring会试图通过名字来找到对应的对象。
@Autowired
@Qualifier("join")
Join join111;
@Qualifier作为一个独立注解存在的主要原因是它可以被应用在构造器参数或方法参数上,但上文提到的@Autowired注解只能运用在构造器或方法本身。
public SpringTest(@Qualifier("join")Join join){
}
看下@Qualifier的定义
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public@interfaceQualifier
@TransactionConfiguration
为配置事务性测试定义了类级别的元数据。特别地,如果需要的PlatformTransactionManager不是“transactionManager”的话, 那么可以显式配置驱动事务的PlatformTransactionManager
的bean名字。此外, 可以将defaultRollback
标志改为false
。通常, @TransactionConfiguration
与@ContextConfiguration
搭配使用。
@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
publicclass SpringTest
@BeforeTransaction
表明被注解的public void
方法应该在测试方法的事务开始之前执行, 该事务是通过@Transactional
注解来配置的。
@AfterTransaction
表明被注解的public void
方法应该在测试方法的事务结束之后执行, 该事务是通过@Transactional
注解来配置的。
标注 @Before 或 @After 注解的方法和测试方法运行在同一个事务中,但有时我们希望在测试方法的事务开始之前或完成之后执行某些方法以便获取数据库现场的一些情况。这时,可以使用 Spring TestContext 的 @BeforeTransaction 和 @AfterTransaction 注解来达到目录(这两个注解位于 org.springframework.test.context.transaction 包中)。
JUnit测试说明
常用注解
@Before:初始化方法
@After:释放资源
@Test:测试方法,在这里可以测试期望异常和超时时间
@Ignore:忽略的测试方法
@BeforeClass:针对所有测试,只执行一次,且必须为static void
@AfterClass:针对所有测试,只执行一次,且必须为static void
JUnit4单元测试用例执行顺序:
@BeforeClass ==> @Before ==> @Test ==> @After ==> @AfterClass
相关推荐
`Junit` 提供了注解(如`@Test`)来标记测试方法,可以方便地组织测试类和方法,并且支持测试套件、参数化测试、异常测试等高级特性。使用`Junit`,开发者可以快速地编写出简洁、可读性强的测试代码,从而确保代码...
通常使用的是dbunit核心库和spring-test-dbunit库,后者提供了与Spring集成的便利。 Maven示例: ```xml <groupId>org.dbunit <artifactId>dbunit <version>3.6.2 <scope>test <groupId>...
1. **配置Spring测试环境**:使用Spring Test模块,创建一个继承自`AbstractTransactionalDataSourceSpringContextTests`或`AbstractTransactionalJUnit4SpringContextTests`的测试类。这两个类提供了事务管理,确保...
首先,为了在 Spring Boot 项目中使用 DBUnit,我们需要添加 DBUnit 的依赖。这可以通过在 `build.gradle` 或 `pom.xml` 文件中引入相应的坐标来完成。例如,在 Gradle 中,可以添加如下依赖: ```groovy ...
9. **@Before/@After 和 @BeforeEach/@AfterEach**:这些JUnit注解可以在每个测试方法之前和之后执行一些设置或清理工作。 10. **Spring TestDBUnit**:这是一个扩展,结合了Spring TestContext Framework和DBUnit...
通过JUnit、Spring Test和dbunit,我们可以对每个部分进行有效的测试,确保代码的正确性和稳定性。在实际项目中,一个良好的测试策略能够帮助我们更快地发现和修复问题,提高开发效率,这也是通向架构师道路的关键...
【dbunit-spring-demo】是一个基于Java的项目,它展示了如何在Spring框架中有效地使用DBUnit工具进行数据库测试。DBUnit是JUnit的一个扩展,专门用于数据库的集成测试,它允许开发者在测试之前填充数据库,执行测试...
DBUnit通过JUnit注解(如`@Before`和`@After`)来触发数据的导入和导出。 例如,以下是一个简单的DBUnit测试用例: ```java import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.xml.FlatXmlDataSet; ...
Spring DBUnit 提供了 Spring 测试框架和 DBUnit 项目,允许你通过注解来实现测试的一些准备工作。 示例代码: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @TestExecutionListeners({ ...
在Spring3中,我们可以使用JUnit作为基础测试框架,配合Spring的`@ContextConfiguration`注解加载应用上下文,`@Autowired`注解注入依赖,以及`@Test`注解定义测试方法。例如,我们可以创建一个测试类,通过`@...
- **新注解**:简化了测试代码的编写,例如`@Test`用于标记测试方法,`@Before`和`@After`用于设置和清理操作。 - **异常处理**:改进了异常捕获机制,使得异常处理更加灵活。 - **断言方法**:增加了更多类型的断言...
在上面的代码中,我们使用 `@Configuration` 注解来配置 DBUnit,我们定义了一个名为 `databaseConfig` 的 Bean,其中包含了 DBUnit 的配置信息。同时,我们还定义了一个名为 `dataSource` 的 Bean,其中包含了数据...
DBUnit可以用来设置和清理测试数据,它与JUnit结合使用,能够在每次测试前后恢复数据库到已知状态。 4. **Spring Test模块**:Spring Boot提供了集成测试的支持,包括Spring Test和Spring Boot Test。这些模块可以...
- **JUnit**: JUnit是最早也是最广泛使用的Java单元测试框架之一,主要用于编写和运行测试用例。它支持注解驱动的测试方法,但其版本迭代相对缓慢,部分高级特性支持不如新框架。 - **TestNG**: TestNG是一个基于...
2. 使用@Test注解:在JUnit测试类中,为每个测试方法添加@Test注解,然后编写测试逻辑。测试方法通常会模拟输入参数,调用待测试的方法,并验证返回结果或数据库状态。 3. 测试事务管理:由于iBatis和Spring都是...
4. **数据导入**:使用 dbunit-mongodb 提供的 API,将数据集加载到 MongoDB 中,初始化测试环境。 5. **执行测试**:在 JUnit 测试类中,编写测试方法,对 MongoDB 中的数据进行操作并验证结果。 6. **数据清理**:...
8. **单元测试和集成测试**:为了确保系统功能的正确性,开发过程中会使用JUnit、Mockito等工具进行单元测试,以及Spring Test和DbUnit等进行集成测试。 在pelDem这个项目中,我们可以期待看到上述知识点的具体应用...
DbUnit 不仅限于基本的数据导入导出,还可以与其他工具如 Hibernate 和 Spring 整合,实现更复杂的数据库操作。此外,它在集成测试、回归测试以及数据迁移场景中也有广泛的应用。 总结,DbUnit 是 Java 开发者在...
使用JUnit和Mockito进行单元测试,通过Spring Test和DBUnit进行集成测试,确保代码的质量和稳定性。 六、代码质量管理与重构 SpringSide 4 遵循良好的编码规范,如SOLID原则,以及代码重构的最佳实践。通过学习...
在测试类中,利用Spring Test的`@Before`和`@After`注解来调用DBUnit的方法初始化和清理数据库。 4. **使用DBUnit的步骤**: - **准备数据集**:定义数据集文件,例如XML格式,包含测试所需的数据库记录。 - **...