11.3 JDBC测试支持
org.springframework.test.jdbc是包含JdbcTestUtils的包,它是一个JDBC相关的工具方法集,意在简化标准数据库测试场景。特别地,JdbcTestUtils提供以下静态工具方法:
- countRowsInTable(..):统计给定表的行数。
- countRowsInTableWhere(..):使用提供的where语句进行筛选统计给定表的行数。
- deleteFromTables(..):删除特定表的全部数据。
- deleteFromTableWhere(..):使用提供的where语句进行筛选并删除给定表的数据。
- dropTables(..):删除指定的表。
注意AbstractTransactionalJUnit4SpringContextTests和AbstractTransactionalTestNGSpringContextTests 提供了委托给前面所述的JdbcTestUtils中的方法的简便方法。
spring-jdbc模块提供了配置和启动嵌入式数据库的支持,可用于与数据库交互的集成测试中。
详见Section 15.8, “嵌入式数据库支持”和 ection 15.8.5, “使用嵌入式数据库测试数据访问逻辑”。
11.4 注解
11.4.1 Spring测试注解
Spring框架提供以下Spring特定的注解集合,你可以在单元和集成测试中协同TestContext框架使用它们。请参考相应的JAVA帮助文档作进一步了解,包括默认的属性,属性别名等等。、
@BootstrapWith
@BootstrapWith是一个用于配置Spring TestContext框架如何引导的类级别的注解。具体地说,@BootstrapWith用于指定一个自定义的TestContextBootstrapper。请查看引导TestContext框架作进一步了解。
@ContextConfiguration
@ContextConfiguration定义了类级别的元数据来决定如何为集成测试来加载和配置应用程序上下文。具体地说,@ContextConfiguration声明了用于加载上下文的应用程序上下文资源路径和注解类。
资源路径通常是类路径中的XML配置文件或者Groovy脚本;而注解类通常是使用@Configuration注解的类。但是,资源路径也可以指向文件系统中的文件和脚本,解决类也可能是组件类等等。
1 |
@ContextConfiguration("/test-config.xml")
|
2 |
public class XmlApplicationContextTests {
|
1 |
@ContextConfiguration(classes = TestConfig.class)
|
2 |
public class ConfigClassApplicationContextTests {
|
作为声明资源路径或注解类的替代方案或补充,@ContextConfiguration可以用于声明ApplicationContextInitializer类。
1 |
@ContextConfiguration(initializers = CustomContextIntializer.class)
|
2 |
public class ContextInitializerTests {
|
@ContextConfiguration偶尔也被用作声明ContextLoader策略。但注意,通常你不需要显示的配置加载器,因为默认的加载器已经支持资源路径或者注解类以及初始化器。
1 |
@ContextConfiguration(locations = "/test-context.xml", loader = CustomContextLoader.class)
|
2 |
public class CustomLoaderXmlApplicationContextTests {
|
|
@ContextConfiguration默认对继承父类定义的资源路径或者配置类以及上下文初始化器提供支持。
|
参阅Section 11.5.4, 上下文管理和@ContextConfiguration帮助文档作进一步了解。
@WebAppConfiguration
@WebAppConfiguration是一个用于声明集成测试所加载的ApplicationContext须是WebApplicationContext的类级别的注解。测试类的@WebAppConfiguration注解只是为了保证用于测试的WebApplicationContext会被加载,它使用”file:src/main/webapp”路径默认值作为web应用的根路径(即,资源基路径)。资源基路径用于幕后创建一个MockServletContext作为测试的WebApplicationContext的ServletContext。
2 |
@WebAppConfiguration("classpath:test-web-resources")
|
3 |
public class WebAppTests {
|
注意@WebAppConfiguration必须和@ContextConfiguration一起使用,或者在同一个测试类,或者在测试类层次结构中。请参阅@WebAppConfiguration帮助文档作进一步了解。
@ContextHierarchy
@ContextHierarchy是一个用于为集成测试定义ApplicationContext层次结构的类级别的注解。@ContextHierarchy应该声明一个或多个@ContextConfiguration实例列表,其中每一个定义上下文层次结构的一个层次。下面的例子展示了在同一个测试类中@ContextHierarchy的使用方法。但是,@ContextHierarchy一样可以用于测试类的层次结构中。
2 |
@ContextConfiguration("/parent-config.xml"),
|
3 |
@ContextConfiguration("/child-config.xml")
|
5 |
public class ContextHierarchyTests {
|
3 |
@ContextConfiguration(classes = AppConfig.class),
|
4 |
@ContextConfiguration(classes = WebConfig.class)
|
6 |
public class WebIntegrationTests {
|
如果你想合并或者覆盖一个测试类的层次结构中的应用程序上下文中指定层次的配置,你就必须在类层次中的每一个相应的层次通过为@ContextConfiguration的name属性提供与该层次相同的值的方式来显示地指定这个层次。请参阅上下文层次关系和@ContextHierarchy帮助文档来获得更多的示例。
@ActiveProfiles
@ActiveProfiles是一个用于当集成测试加载ApplicationContext的时候声明哪一个bean definition profiles被激活的类级别的注解。
3 |
public class DeveloperTests {
|
2 |
@ActiveProfiles({"dev", "integration"})
|
3 |
public class DeveloperIntegrationTests {
|
|
@ActiveProfiles默认为继承激活的在超类声明的 bean definition profiles提供支持。通过实现一个自定义的 ActiveProfilesResolver并通过@ActiveProfiles的resolver属性来注册它的编程的方式来解决激活bean definition profiles问题也是可行的。 |
参阅使用环境profiles来配置上下文和@ActiveProfiles帮助文档作进一步了解。
@TestPropertySource
@TestPropertySource是一个用于为集成测试加载ApplicationContext时配置属性文件的位置和增加到Environment中的PropertySources集中的内联属性的类级别的注解。
测试属性源比那些从系统环境或者Java系统属性以及通过@PropertySource或者编程方式声明方式增加的属性源具有更高的优先级。而且,内联属性比从资源路径加载的属性具有更高的优先级。
下面的例子展示了如何从类路径中声明属性文件。
2 |
@TestPropertySource("/test.properties")
|
3 |
public class MyIntegrationTests {
|
下面的例子展示了如何声明内联属性。
@ContextConfiguration
@TestPropertySource(properties = { “timezone = GMT”, “port: 4242″ })
public class MyIntegrationTests {
// class body…
}
@DirtiesContext
@DirtiesContext指明测试执行期间该Spring应用程序上下文已经被弄脏(也就是说通过某种方式被更改或者破坏——比如,更改单例bean的状态)。当应用程序上下文被标为”脏”,它将从测试框架缓存中被移除并关闭。因此,Spring容器将为随后需要同样配置元数据的测试而被重建。
@DirtiesContext可以在同一个类或者类层次结构中的类级别和方法级别中使用。在这个场景下,应用程序上下文将在任意此注解的方法之前或之后以及当前测试类之前或之后被标为“脏”,这取决于配置的methodMode和classMode。
下面的例子解释了在多种配置场景下什么时候上下文会被标为“脏”。
- 当在一个类中声明并将类模式设为BEFORE_CLASS,则在当前测试类之前。
1 |
@DirtiesContext(classMode = BEFORE_CLASS)
|
2 |
public class FreshContextTests {
|
3 |
// some tests that require a new Spring container |
- 当在一个类中声明并将类模式设为AFTER_CLASS(也就是,默认的类模式),则在当前测试类之后。
2 |
public class ContextDirtyingTests {
|
3 |
// some tests that result in the Spring container being dirtied |
- 当在一个类中声明并将类模式设为BEFORE_EACH_TEST_METHOD,则在当前测试类的每个方法之前。
1 |
@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD)
|
2 |
public class FreshContextTests {
|
3 |
// some tests that require a new Spring container |
- 当在一个类中声明并将类模式设为AFTER_EACH_TEST_METHOD,则在当前测试类的每个方法之后。
1 |
@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD)
|
2 |
public class ContextDirtyingTests {
|
3 |
// some tests that result in the Spring container being dirtied |
- 当在一个方法中声明并将方法模式设为BEFORE_METHOD,则在当前方法之前。
1 |
@DirtiesContext(methodMode = BEFORE_METHOD)
|
3 |
public void testProcessWhichRequiresFreshAppCtx() {
|
4 |
// some logic that requires a new Spring container |
- 当在一个方法中声明并将方法模式设为AFTER_METHOD(也就是说,默认的方法模式),则在当前方法之后。
3 |
public void testProcessWhichDirtiesAppCtx() {
|
4 |
// some logic that results in the Spring container being dirtied |
如果@DirtiesContext被用于上下文被配置为通过@ContextHierarchy定义的上下文层次中的一部分的测试中,则hierarchyMode标志可用于控制如何声明上下文缓存。默认将使用一个穷举算法用于清除包括不仅当前层次而且与当前测试拥有共同祖先的其它上下文层次的缓存。所有在拥有共同祖先上下文的子层次的应用程序上下文都会从上下文中被移除并关闭。如果穷举算法对于特定的使用场景显得有点威力过猛,那么你可以指定一个更简单的当前层算法来代替,如下所。
02 |
@ContextConfiguration("/parent-config.xml"),
|
03 |
@ContextConfiguration("/child-config.xml")
|
05 |
public class BaseTests {
|
09 |
public class ExtendedTests extends BaseTests {
|
12 |
@DirtiesContext(hierarchyMode = CURRENT_LEVEL)
|
14 |
// some logic that results in the child context being dirtied |
参阅DirtiesContext.HierarchyMode帮助文档以获得穷举和当前层算法更详细的了解。
@TestExecutionListeners
@TestExecutionListeners定义了一个类级别的元数据,用于配置需要用TestContextManager进行注册的TestExecutionListener实现。通常,@TestExecutionListeners与@ContextConfiguration一起使用。
2 |
@TestExecutionListeners({CustomTestExecutionListener.class, AnotherTestExecutionListener.class})
|
3 |
public class CustomTestExecutionListenerTests {
|
@TestExecutionListeners默认支持继承监听器。参阅帮助文档获得示例和更详细的了解。
@Commit
@Commit指定事务性的测试方法在测试方法执行完成后对事务进行提交。@Commit可以用作@Rollback(false)的直接替代,以更好的传达代码的意图。和@Rollback一样,@Commit可以在类层次或者方法层级声明。
3 |
public void testProcessWithoutRollback() {
|
@Rollback
@Rollback指明当测试方法执行完毕的时候是否对事务性方法中的事务进行回滚。如果为true,则进行回滚;否则,则提交(请参加@Commit)。在Spring TestContext框架中,集成测试默认的Rollback语义为true,即使你不显示的指定它。
当被声明为方法级别的注解,则@Rollback为特定的方法指定回滚语义,并覆盖类级别的@Rollback和@Commit语义。
@Rollback(false)
@Test
public void testProcessWithoutRollback() {
// …
}
@BeforeTransaction
@BeforeTransaction指明通过Spring的@Transactional注解配置为需要在事务中执行的测试方法在事务开始之前先执行注解的void方法。从Spring框架4.3版本起,@BeforeTransaction方法不再需要为public并可能被声明为基于Java8的接口的默认方法。
@BeforeTransaction
void beforeTransaction() {
// logic to be executed before a transaction is started
}
@AfterTransaction
@AfterTransaction指明通过Spring的@Transactional注解配置为需要在事务中执行的测试方法在事务结束之后执行注解的void方法。从Spring框架4.3版本起,@AfterTransaction方法不再需要为public并可能被声明为基于Java8的接口的默认方法。
@AfterTransaction
void afterTransaction() {
// logic to be executed after a transaction has ended
}
@Sql
@Sql用于注解测试类或者测试方法,以让在集成测试过程中配置的SQL脚本能够在给定的的数据库中得到执行。
2 |
@Sql({"/test-schema.sql", "/test-user-data.sql"})
|
4 |
// execute code that relies on the test schema and test data |
请参阅通过@sql声明执行的SQL脚本作进一步了解。
@SqlConfig
@SqlConfig定义了用于决定如何解析和执行通过@Sql注解配置的SQL脚本。
3 |
scripts = "/test-user-data.sql",
|
4 |
config = @SqlConfig(commentPrefix = "`", separator = "@@")
|
7 |
// execute code that relies on the test data |
@SqlGroup
@SqlGroup是一个用于聚合几个@Sql注解的容器注解。@SqlGroup可以直接使用,通过声明几个嵌套的@Sql注解,也可以与Java8的可重复注解支持协同使用,即简单地在同一个类或方法上声明几个@Sql注解,隐式地产生这个容器注解。
3 |
@Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")),
|
4 |
@Sql("/test-user-data.sql")
|
7 |
// execute code that uses the test schema and test data
|