本节(本章其他部分)涵盖了Spring应用程序的集成测试。它包括如下主题:html
可以执行一些集成测试而无需部署到应用程序服务器或链接到其余企业基础结构,这一点很重要。这样能够测试如下内容:java
Spring框架为Spring测试模块中的集成测试提供了一流的支持。实际的JAR文件的名称可能包括发行版,也可能采用长org.springframework.test
格式,具体取决于你从何处获取(请参阅“依赖管理”部分中的说明)。该库包含org.springframework.test
包,其中包含用于与Spring容器进行集成测试的有价值的类。此测试不依赖于应用程序服务器或其余部署环境。此类测试的运行速度比单元测试慢,但比依赖于部署到应用程序服务器的等效Selenium测试或远程测试快。git
单元和集成测试支持以注解驱动的Spring TestContext 框架的形式提供。TestContext
框架与实际使用的测试框架无关,该框架容许各类环境(包括JUnit,TestNG和其余环境)中对测试进行检测。github
Spring的集成测试支持的主要目标以下:web
接下来的几节描述了每一个目标,并提供了有关实现和配制详细信息的连接。算法
Fixture意思:JUnit提供了编写测试前准备、测试后清理的固定代码,咱们称之为 Fixture
Spring TestContext
框架提供了Spring ApplicationContext
实例和WebApplicationContext
实例的一致加载以及这些上下文的缓存。支持加载上下文的缓存很重要,由于启动时间可能会成为一个问题-不是由于Spring自己的开销,而是由于Spring容器实例化的对象须要时间才能实例化。例如,具备50到100个Hibernate
映射文件的项目可能须要10到20秒来加载映射文件,而且在每一个测试fixture中运行每一个测试以前要承担该消耗,这会致使总体测试运行速度变慢,从而下降了开发人员的工做效率。spring
测试类一般声明XML或Groovy配置元数据的资源位置数组(一般是在类路径中)或用于配置应用程序的组件类的数组。这些位置或类与web.xml
或其余用于生产部署的配置文件中指定的位置或类相同或类似。sql
默认状况下,加载后,已配置的ApplicationContext
将从新用每一个测试。所以,每一个测试套件仅产生一次安装成本,而且随后的测试执行要快得多。在这种状况下,术语“测试套件”是指全部测试都在相同JVM中运行,例如,全部测试都从给定项目或模块的Ant
、Maven
或Gradle
构建运行。在不太可能的状况下,测试破坏了应用程序上下文并须要从新加载(例如,经过修改bean定义或应用程序对象的状态),能够将TestContext
框架配置为从新加载配置并重建应用程序上下文,而后再执行下一个测试。数据库
请参见使用TestContext框架进行上下文管理和上下文缓存。express
当TestContext
框架加载你的应用程序上下文时,能够选择地用依赖注入来配置测试类的实例。这提供了一种方便的机制,能够经过在应用程序上下文中使用预配置的bean来设置测试fixture
。这里一个强大的好处是,你能够跨各类测试场景重用应用程序上下文(例如,用于配置spring管理的对象图、事务代理、数据源实例等),从而避免为单个测试用例重复复杂的测试fixture
设置。
例如,考虑一个场景,其中咱们有一个类(HibernateTitleRepository
),该类为Title域实体实现数据访问逻辑。咱们要编写集成测试来测试如下方面:
HibernateTitleRepository
bean的配置有关的一切都正确并存在吗?Hibernate
映射文件配置:是否已正确映射全部内容,而且是否有正确的延迟加载配置?HibernateTitleRepository
的逻辑:此类的配置实例是否按预期执行?请参见使用TestContext框架进行测试fixture
的依赖注入。
访问真实数据库的测试中的一个常见问题是它们对持久存储状态的影响。即便使用开发数据库,对状态的更改也可能会影响之后的测试。一样,许多操做(例如插入或修改持久数据)没法在事物以外执行(或验证)。
TestContext
框架解决了这个问题。默认状况下,框架为每一个测试建立并回滚事务。你能够编写能够假定存在事务的代码。若是在测试中调用事务代理对象,则对象将根据其配置事务语义正确运行。此外,若是测试方法在测试管理的事务中运行时删除了选定表的内容,则该事务将默认回滚,而且数据库将返回到执行测试以前的状态。经过使用在测试的应用程序上下文中定义的PlatformTransactionManager
bean,能够为测试提供事务支持。
若是你想要提交一个事务(不常见,可是当你想要一个特定的测试填充或修改数据库时,偶尔会有用),你能够经过使用@Commit
注解告诉TestContext
框架使事务提交而不是回滚。
请参阅使用TestContext框架进行事务管理。
Spring TestContext
框架提供了几个抽象支持类,这些基础测试类为测试框架提供了定义明确的钩子,以方便的实例变量和方法,可用于访问如下内容:
另外,你可能但愿使用针对你的项目的实例变量和方法构建本身的自定义,应用程序范围的超类。
请参阅TestContext框架的支持类。
org.springframework.test.jdbc
包包含JdbcTestUtils
,它是JDBC相关实用程序功能的集合,旨在简化标准数据库测试方案。具体来讲,JdbcTestUtils
提供如下静态实用程序方法。
countRowsInTable(..)
:计算给定表中的行数。countRowsInTableWhere(..)
:使用提供的WHERE
子句计算给定表中的行数。deleteFromTables(..)
:删除指定表中的全部行。deleteFromTableWhere(..)
: 使用提供的WHERE
子句从给定表中删除行。AbstractTransactionalJUnit4SpringContextTests
和AbstractTransactionalTestNGSpringContextTests
提供了便利的方法,这些方法委托给JdbcTestUtils
中的上述方法。spring-jdbc
模块提供了对配置和启动嵌入式数据库的支持你能够在与数据库交互的集成测试中使用它。有关详细信息,请参见 嵌入式数据库支持和使用 嵌入式数据库测试数据访问逻辑。
本节介绍了在测试Spring应用程序时可使用的注解。它包括如下主题:
Spring框架提供了如下特定于Spring的注解集,你能够在单元测试和集成测试中将它们与TestContext
框架结合使用。有关更多信息,请参见相应的javadoc,包括默认属性值、属性别名和其余详细信息。
Spring的测试注解包括如下内容:
@BootstrapWith
@ContextConfiguration
@WebAppConfiguration
@ContextHierarchy
@ActiveProfiles
@TestPropertySource
@DynamicPropertySource
@DirtiesContext
@TestExecutionListeners
@Commit
@Rollback
@BeforeTransaction
@AfterTransaction
@Sql
@SqlConfig
@SqlMergeMode
@SqlGroup
@BootstrapWith
@BootstrapWith
是一个类级别的注解,可用于配置如何引导Spring TestContext
框架。具体来讲,你可使用@BootstrapWith
指定自定义TestContextBootstrapper
。有关更多详细信息,请参见有关引导TestContext框架的部分。
参考代码:
org.liyong.test.annotation.test.spring.ConfigClassApplicationContextTests
@ContextConfiguration
@ContextConfiguration
定义了用于肯定如何为集成测试加载和配置ApplicationContext
的类级元数据。具体来讲,@ContextConfiguration
声明应用程序上下文资源位置或用于加载上下文的组件类。
资源位置一般是位于类路径中的XML配置文件或Groovy脚本,而组件类一般是@Configuration
类。可是,资源位置也能够引用文件系统中的文件和脚本,组件类能够是@Component
类、@Service
类等等。有关更多详细信息,请参见组件类。
如下示例显示了一个指向XML文件的@ContextConfiguration
注解:
@ContextConfiguration("/test-config.xml") // class XmlApplicationContextTests { // class body... }
如下示例显示了一个@ContextConfiguration
注解,该注解引用了一个类:
@ContextConfiguration(classes = TestConfig.class) //1 class ConfigClassApplicationContextTests { // class body... }
参考代码:
org.liyong.test.annotation.test.spring.ConfigClassApplicationContextTests
做为声明资源位置或组件类的替代方法或补充,可使用@ContextConfiguration
声明ApplicationContextInitializer
类。如下示例显示了这种状况:
@ContextConfiguration(initializers = CustomContextIntializer.class) class ContextInitializerTests { // class body... }
参考代码:
org.liyong.test.annotation.test.spring.ContextInitializerTests
你能够选择使用@ContextConfiguration
来声明ContextLoader
策略。可是,你一般不须要显式配置加载器,由于默认加载器支持初始化程序以及资源位置或组件类。
如下示例同时使用配置位置和加载器:
@ContextConfiguration(locations = "/test-context.xml", loader = CustomContextLoader.class) //1 class CustomLoaderXmlApplicationContextTests { // class body... }
@ContextConfiguration
为继承资源位置或配置类以及超类声明上下文初始化器提供支持。
有关更多详细信息,请参见上下文管理和@ContextConfiguration
javadocs。
参考代码:
org.liyong.test.annotation.test.spring.CustomLoaderXmlApplicationContextTests
@WebAppConfiguration
@WebAppConfiguration
是一个类级别的注解,可用于声明为集成测试加载的ApplicationContext
应该是WebApplicationContext
。@WebAppConfiguration
仅存在于测试类上,能够确保为测试加@WebApplicationContext
,并使用默认值file:src/main/webapp
做为Web应用程序根目录(也就是即资源基本路径)。资源基础路径用于在后台建立MockServletContext
,该MockServletContext
用做测试的WebApplicationContext
的ServletContext
。
如下示例显示了如何使用@WebAppConfiguration
注解:
@ContextConfiguration @WebAppConfiguration // class WebAppTests { // class body... }
要覆盖默认值,可使用隐式值属性指定其余基础资源路径。classpath:
和file:
资源前缀均受支持。若是未提供资源前缀,则假定该路径是文件系统资源。如下示例显示如何指定类路径资源:
@ContextConfiguration @WebAppConfiguration("classpath:test-web-resources") //1 class WebAppTests { // class body... }
注意,@WebAppConfiguration
必须与@ContextConfiguration
一块儿使用,能够在单个测试类中使用,也能够在测试类层次结构中使用。
有关更多详细信息,请参见@WebAppConfiguration javadoc。
参考代码:
org.liyong.test.annotation.test.spring.WebAppTests
@ContextHierarchy
@ContextHierarchy
是一个类级注解,用于定义集成测试的ApplicationContext
实例的层次结构。 @ContextHierarchy
应该用一个或多个@ContextConfiguration
实例的列表声明,每一个实例定义上下文层次结构中的一个级别。如下示例演示了在单个测试类中使用@ContextHierarchy
(也能够在测试类层次结构中使用@ContextHierarchy
):
@ContextHierarchy({ @ContextConfiguration("/parent-config.xml"), @ContextConfiguration("/child-config.xml") }) class ContextHierarchyTests { // class body... }
参考代码:
org.liyong.test.annotation.test.spring.ContextHierarchyTests
@WebAppConfiguration @ContextHierarchy({ @ContextConfiguration(classes = AppConfig.class), @ContextConfiguration(classes = WebConfig.class) }) class WebIntegrationTests { // class body... }
参考代码:
org.liyong.test.annotation.test.spring.WebIntegrationTests
若是须要合并或覆盖测试类层次结构中上下文层次结构的给定级别的配置,则必须经过在类层次结构的每一个对应级别上为@ContextConfiguration
中的name属性提供相同的值来显式地命名该级别。有关更多示例,请参见上下文层次结构和@ContextHierarchy
javadoc。
@ActiveProfiles
@ActiveProfiles
是一个类级别的注解,用于声明在为集成测时加载ApplicationContext
时应启用哪些bean定义配置文件。
如下示例代表dev
配置文件应处于活动状态:
@ContextConfiguration @ActiveProfiles("dev") //1 class DeveloperTests { // class body... }
如下示例代表dev
和integration
配置文件均应处于活动状态:
@ContextConfiguration @ActiveProfiles({"dev", "integration"}) //1 class DeveloperIntegrationTests { // class body... }
dev
和integration
配置文件应该处于活动状态。@ActiveProfiles
提供了对继承默认状况下超类声明的活动bean定义配置文件的支持。你还能够经过实现自定义ActiveProfilesResolver
并使用@ActiveProfiles
的resolver
属性对其进行注册,以编程方式解析活动bean定义配置文件。
参见环境配置文件和@ActiveProfiles javadoc的上下文配置以得到示例和更多细节。
参考代码:
org.liyong.test.annotation.test.spring.DeveloperIntegrationTests
@TestPropertySource
@TestPropertySource
是类级别的注解,可用于配置属性文件和内联属性的位置,这些属性和内联属性将被添加到环境中针对集成测试加载的ApplicationContext
的PropertySources
集中。
下面的示例演示如何从类路径声明属性文件:
@ContextConfiguration @TestPropertySource("/test.properties") //1 class MyIntegrationTests { // class body... }
下面的示例演示如何声明内联属性:
@ContextConfiguration @TestPropertySource(properties = { "timezone = GMT", "port: 4242" }) //1 class MyIntegrationTests { // class body... }
有关示例和更多详细信息,请参见使用测试属性源进行上下文配置。
@DynamicPropertySource
@DynamicPropertySource
是方法级别的注解,可用于注册动态属性,以将动态属性添加到环境中针对集成测试加载的ApplicationContext
的PropertySources
集中。当你不预先知道属性的值时,例如,若是属性是由外部资源管理的,例如由Testcontainers
项目管理的容器,则动态属性颇有用。
下面的示例演示如何注册动态属性:
@ContextConfiguration class MyIntegrationTests { static MyExternalServer server = // ... @DynamicPropertySource //1 static void dynamicProperties(DynamicPropertyRegistry registry) { //2 registry.add("server.port", server::getPort); //3 } // tests ... }
@DynamicPropertySource
注解静态方法。DynamicPropertyRegistry
做为参数。server.port
属性。有关更多详细信息,请参见使用动态属性源进行上下文配置。
@DirtiesContext
@DirtiesContext
表示底层的Spring ApplicationContext
在执行测试期间已被清理(即,该测试以某种方式修改或破坏了它(例如,经过更改单例bean的状态)),应将其关闭。当应用程序上下文被标记为清理时,它将从测试框架的缓存中删除并关闭。所以,对于须要具备相同配置元数据的上下文的后续测试,将从新构建底层Spring容器。
你能够将@DirtiesContext
用做同一类或类层次结构中的类级别和方法级别的注解。在这种状况下,取决于配置的methodMode
和classMode
,在任何此类带注解的方法以前或以后以及当前测试类以前或以后,ApplicationContext
均标记为清理。
如下示例说明了在各类配置状况下什么时候清理上下文:
在当前测试类以前,在类模式设置为BEFORE_CLASS
的类上声明时。
@DirtiesContext(classMode = BEFORE_CLASS) //1 class FreshContextTests { // some tests that require a new Spring container }
在当前测试类以后,当在类模式设置为AFTER_CLASS
(即默认类模式)的类上声明时。
@DirtiesContext class ContextDirtyingTests { // some tests that result in the Spring container being dirtied }
在当前测试类中的每一个测试方法以后,在类模式设置为AFTER_EACH_TEST_METHOD
的类上声明时。
@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD) class ContextDirtyingTests { // some tests that result in the Spring container being dirtied }
在当前测试以前,当在方法模式设置为BEFORE_METHOD
的方法上声明时。
@DirtiesContext(methodMode = BEFORE_METHOD) //1 @Test void testProcessWhichRequiresFreshAppCtx() { // some logic that requires a new Spring container }
当前测试以后,当在方法模式设置为AFTER_METHOD
的方法上声明时(即默认方法模式)。
@DirtiesContext //1 @Test void testProcessWhichDirtiesAppCtx() { // some logic that results in the Spring container being dirtied }
若是在使用@ContextHierarchy
将上下文配置为上下文层次结构的一部分的测试中使用@DirtiesContext
,则可使用hierarchyMode
标志控制清除上下文缓存的方式。默认状况下,使用穷举算法清除上下文缓存,不只包括当前级别,还包括共享当前测试共有的祖先上下文的全部其余上下文层次结构。驻留在公共祖先上下文的子层次结构中的全部ApplicationContext
实例都将从上下文缓存中删除并关闭。若是穷举算法对于特定用例来讲过于强大,那么你能够指定更简单的当前级别算法,以下面的示例所示。
@ContextHierarchy({ @ContextConfiguration("/parent-config.xml"), @ContextConfiguration("/child-config.xml") }) class BaseTests { // class body... } class ExtendedTests extends BaseTests { @Test @DirtiesContext(hierarchyMode = CURRENT_LEVEL) //1 void test() { // some logic that results in the child context being dirtied } }
有关EXHAUSTIVE
和CURRENT_LEVEL
算法的更多详细信息,请参见DirtiesContext.HierarchyMode javadoc。
@TestExecutionListeners
@TestExecutionListeners
定义了用于配置应在TestContextManager
中注册的TestExecutionListener
实现的类级元数据。一般,@TestExecutionListeners
与@ContextConfiguration
结合使用。
下面的示例演示如何注册两个TestExecutionListener
实现:
@ContextConfiguration @TestExecutionListeners({CustomTestExecutionListener.class, AnotherTestExecutionListener.class}) //1 class CustomTestExecutionListenerTests { // class body... }
TestExecutionListener
实现。默认状况下,@TestExecutionListeners
支持继承的监听器。有关示例和更多详细信息,请参见javadoc。
@Commit
@Commit
表示应在测试方法完成后提交用于事务性测试方法的事务。你能够将@Commit
用做@Rollback(false)
的直接替代品,以更明确地传达代码的意图。与@Rollback
相似,@ Commit
也能够声明为类级别或方法级别的注解。
如下示例显示了如何使用@Commit
注解:
@Commit //1 @Test void testProcessWithoutRollback() { // ... }
@Rollback
@Rollback
表示在测试方法完成后是否应回退用于事务性测试方法的事务。若是为true,则回滚该事务。不然,将提交事务(另请参见@Commit)。即便未明确声明@Rollback
,Spring TestContext
框架中用于集成测试的回滚默认为true。
当声明为类级注解时,@Rollback
定义测试类层次结构中全部测试方法的默认回滚语义。当声明为方法级别的注解时,@Rollback
定义特定测试方法的回滚语义,从而可能覆盖类级别的@Rollback
或@Commit
语义。
如下示例使测试方法的结果不回滚(即,结果已提交到数据库):
@Rollback(false) //1 @Test void testProcessWithoutRollback() { // ... }
@BeforeTransaction
@BeforeTransaction
表示,对于已配置为使用Spring的@Transactional
注解在事务内运行的测试方法,带注解的void方法应在事务开始以前运行。@BeforeTransaction
方法不须要public访问限定,能够在基于Java 8的接口默认方法。
如下示例显示了如何使用@BeforeTransaction
注解:
@BeforeTransaction //1 void beforeTransaction() { // logic to be executed before a transaction is started }
@AfterTransaction
@AfterTransaction
表示,对于已配置为经过使用Spring的@Transactional
注解在事务内运行的测试方法,带注解的void方法应在事务结束后运行。@AfterTransaction
方法不须要public访问限定,能够在基于Java 8的接口默认方法中声明。
@AfterTransaction //1 void afterTransaction() { // logic to be executed after a transaction has ended }
@Sql
@Sql
用于注解测试类或测试方法,以配置在集成测试期间针对给定数据库运行的SQL脚本。如下示例显示了如何使用它:
@Test @Sql({"/test-schema.sql", "/test-user-data.sql"})//1 void userTest() { // execute code that relies on the test schema and test data }
有关更多详细信息,请参见使用@Sql声明式执行SQL脚本。
@SqlConfig
@SqlConfig
定义元数据,该元数据用于肯定如何解析和运行使用@Sql
注解配置的SQL脚本。如下示例显示了如何使用它:
@Test @Sql( scripts = "/test-user-data.sql", config = @SqlConfig(commentPrefix = "`", separator = "@@") // ) void userTest() { // execute code that relies on the test data }
@SqlMergeMode
@SqlMergeMode
用于注释测试类或测试方法,以配置是否将方法级@Sql
声明与类级@Sql
声明合并。若是未在测试类或测试方法上声明@SqlMergeMode
,则默认状况下将使用OVERRIDE
合并模式。在OVERRIDE
模式下,方法级别的@Sql
声明将有效地覆盖类级别的@Sql
声明。
请注意,方法级别的@SqlMergeMode
声明将覆盖类级别的声明。
下面的示例演示如何在类级别使用@SqlMergeMode
。
@SpringJUnitConfig(TestConfig.class) @Sql("/test-schema.sql") @SqlMergeMode(MERGE) //1 class UserTests { @Test @Sql("/user-test-data-001.sql") void standardUserProfile() { // execute code that relies on test data set 001 } }
@Sql
合并模式设置为MERGE
。下面的示例演示如何在方法级别使用@SqlMergeMode
。
@SpringJUnitConfig(TestConfig.class) @Sql("/test-schema.sql") class UserTests { @Test @Sql("/user-test-data-001.sql") @SqlMergeMode(MERGE) //1 void standardUserProfile() { // execute code that relies on test data set 001 } }
对于特定的测试方法,将@Sql
合并模式设置为MERGE
。
@SqlGroup
@SqlGroup
是一个容器注解,它聚合了多个@Sql
注解。你能够本地使用@SqlGroup
声明多个嵌套的@Sql
注解,也能够将其与Java 8对可重复注解的支持结合使用,其中@Sql
能够在同一类或方法上屡次声明,从而隐式生成此容器注解。下面的示例显示如何声明一个SQL组:
@Test @SqlGroup({ //1 @Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")), @Sql("/test-user-data.sql") )} void userTest() { // execute code that uses the test schema and test data }
Spring TestContext
框架的全部配置的标准语义都支持如下注解。请注意,这些注解并不是特定于测试,能够在Spring 框架中的任何地方使用。
@Autowired
@Qualifier
@Value
@Resource
(javax.annotation
) 若是支持JSR-250@ManagedBean
(javax.annotation
) 若是支持 JSR-250@Inject
(javax.inject
) 若是支持 JSR-330@Named
(javax.inject
) 若是支持 JSR-330@PersistenceContext
(javax.persistence
) 若是支持JPA@PersistenceUnit
(javax.persistence
) 若是支持JPA@Required
@Transactional
(org.springframework.transaction.annotation
) with limited attribute supportJSR-250生命周期注解在Spring
TestContext
框架中,能够在ApplicationContext
中配置的任何应用程序组件上使用具备标准语义的@PostConstruct
和@PreDestroy
。可是,这些生命周期注解在实际测试类中的使用受到限制。若是测试类中的方法使用
@PostConstruct
进行注解,则该方法将在基础测试框架的before
方法以前运行(例如,使用JUnit Jupiter的@BeforeEach
注解的方法),而且该方法适用于测试类中的每一个测试方法。另外一方面,若是测试类中的方法使用@PreDestroy
注解,则该方法将永远不会运行。所以,在测试类中,建议你使用来自基础测试框架的测试生命周期回调,而不是@PostConstruct
和@PreDestroy
。
如下注解仅在与SpringRunner、Spring的JUnit 4规则或Spring的JUnit 4支持类一块儿使用时才受支持:
@IfProfileValue
@IfProfileValue
表示已为特定测试环境启用带注解的测试。若是配置的ProfileValueSource
返回提供的名称的匹配值,则使用测试。不然,测试将被禁用,而且实际上将被忽略。
你能够在类级别、方法级别或二者上应用@IfProfileValue
。对于该类或其子类中的任何方法,@IfProfileValue
的类级别用法优先于方法级别用法。具体来讲,若是在类级别和方法级别都启用了测试,则启用该测试。缺乏@IfProfileValue
意味着隐式启用了测试。这相似于JUnit 4的@Ignore
注解的语义,不一样之处在于@Ignore
的存在始终会禁用测试。
如下示例显示了具备@IfProfileValue
注解的测试:
@IfProfileValue(name="java.vendor", value="Oracle Corporation") //1 @Test public void testProcessWhichRunsOnlyOnOracleJvm() { // some logic that should run only on Java VMs from Oracle Corporation }
另外,你能够为@IfProfileValue
配置值列表(具备OR
语义)以在JUnit 4环境中实现相似于TestNG的测试组支持。考虑如下示例:
@IfProfileValue(name="test-groups", values={"unit-tests", "integration-tests"}) //1 @Test public void testProcessWhichRunsForUnitOrIntegrationTestGroups() { // some logic that should run only for unit and integration test groups }
@ProfileValueSourceConfiguration
@ProfileValueSourceConfiguration
是一个类级别的注解,它指定检索经过@IfProfileValue
注解配置的配置文件值时要使用哪一种ProfileValueSource
类型。若是未为测试声明@ProfileValueSourceConfiguration
,则默认使用SystemProfileValueSource
。如下示例显示了如何使用@ProfileValueSourceConfiguration
:
@ProfileValueSourceConfiguration(CustomProfileValueSource.class) //1 public class CustomProfileValueSourceTests { // class body... }
参考代码:
org.liyong.test.annotation.test.spring.ProfileValueTest
@Timed
@Timed
表示带注解的测试方法必须在指定的时间段(以毫秒为单位)内完成执行。若是单元测试片断执行时间超过指定的时间段,则测试将失败。
该时间段包括运行测试方法自己,测试的任何重复(请参见@Repeat
)以及测试套件的任何设置或拆除。如下示例显示了如何使用它:
@Timed(millis = 1000)//1 public void testProcessWithOneSecondTimeout() { // some logic that should not take longer than 1 second to execute }
Spring的@Timed
注解与JUnit 4的@Test(timeout = ...)
支持具备不一样的语义。具体来讲,因为JUnit 4处理测试执行超时的方式(即经过在单独的线程中执行测试方法),若是测试花费的时间太长,@Test(timeout = ...)
会抢先经过测试。另外一方面,Spring的@Timed
不会抢先经过测试,而是在失败以前等待测试完成。
@Repeat
@Repeat
表示必须重复运行带注解的测试方法。注解中指定了要执行测试方法的次数。重复执行的范围包括测试方法自己的执行以及测试套件中任何安装或拆除。如下示例显示了如何使用@Repeat
注解:
@Repeat(10) //1 @Test public void testProcessRepeatedly() { // ... }
如下注解仅在与SpringExtension
和JUnit Jupiter
(即JUnit 5中的编程模型)结合使用时才受支持:
@SpringJUnitConfig
@SpringJUnitConfig
是一个组合注解,它将JUnit Jupiter
中的@ExtendWith(SpringExtension.class)
与Spring TestContext
框架中的@ContextConfiguration
组合在一块儿。它能够在类级别用做@ContextConfiguration
的直接替代。关于配置选项,@ContextConfiguration
和@SpringJUnitConfig
之间的惟一区别是可使用@SpringJUnitConfig
中的value属性声明组件类。
如下示例显示如何使用@SpringJUnitConfig
注解指定配置类:
@SpringJUnitConfig(TestConfig.class) //1 class ConfigurationClassJUnitJupiterSpringTests { // class body... }
如下示例显示如何使用@SpringJUnitConfig
注解指定配置文件的位置:
@SpringJUnitConfig(locations = "/test-config.xml") //1 class XmlJUnitJupiterSpringTests { // class body... }
有关更多详细信息,请参见上下文管理以及@SpringJUnitConfig
和@ContextConfiguration
的javadoc。
@SpringJUnitWebConfig
@SpringJUnitWebConfig
是一个组合的注解,它未来自JUnit Jupiter
的@ExtendWith(SpringExtension.class)
与来自Spring TestContext
框架的@ContextConfiguration
和@WebAppConfiguration
组合在一块儿。你能够在类级别使用它做为@ContextConfiguration
和@WebAppConfiguration
的直接替代。关于配置选项,@ ContextConfiguration
和@SpringJUnitWebConfig
之间的惟一区别是可使用@SpringJUnitWebConfig
中的value属性来声明组件类。另外,只能使用@SpringJUnitWebConfig
中的resourcePath
属性来覆盖@WebAppConfiguration
中的value
属性。
如下示例显示如何使用@SpringJUnitWebConfig
注解指定配置类:
@SpringJUnitWebConfig(TestConfig.class) //1 class ConfigurationClassJUnitJupiterSpringWebTests { // class body... }
如下示例显示如何使用@SpringJUnitWebConfig注解指定配置文件的位置:
@SpringJUnitWebConfig(locations = "/test-config.xml") //1 class XmlJUnitJupiterSpringWebTests { // class body... }
有关更多详细信息,请参见上下文管理以及@SpringJUnitWebConfig,@ContextConfiguration和@WebAppConfiguration的javadoc。
参考代码:
org.liyong.test.annotation.test.spring.ConfigurationClassJUnitJupiterSpringWebTests
@TestConstructor
@TestConstructor
是类型级别的注解,用于配置如何从测试的ApplicationContext
中的组件自动链接测试类构造函数的参数。
若是在测试类上不存在@TestConstructor
或meta-present
,则将使用默认的测试构造函数自动装配模式。有关如何更改默认模式的详细信息,请参见下面的提示。可是请注意,构造函数上的@Autowired
本地声明优先于@TestConstructor
和默认模式。
更改默认的测试构造函数自动装配模式能够经过将JVM系统属性
spring.test.constructor.autowire.mode
设置为all来更改默认的测试构造函数自动装配模式。或者,能够经过SpringProperties
机制更改默认模式。若是未设置
spring.test.constructor.autowire.mode
属性,则不会自动装配测试类构造函数。从Spring框架5.2开始,仅将
@TestConstructor
与SpringExtension
结合使用以与JUnit Jupiter一块儿使用。请注意,SpringExtension
一般会自动为你注册-例如,在使用@SpringJUnitConfig
和@SpringJUnitWebConfig
之类的注解或Spring Boot Test中与测试相关的各类注解时。
@EnabledIf
@EnabledIf
用于表示已注解的JUnit Jupiter测试类或测试方法启用,若是提供的表达式的值为true
,则应运行@EnabledIf
。具体来讲,若是表达式的计算结果为Boolean.TRUE
或等于true
的字符串(忽略大小写),则启用测试。在类级别应用时,默认状况下也会自动启用该类中的全部测试方法。
表达式能够是如下任意一种:
@EnabledIf("#{systemProperties['os.name'].toLowerCase().contains('mac')}")
Environment
中可用属性的占位符。例如:@EnabledIf("${smoke.tests.enabled}")
@EnabledIf("true")
可是请注意,不是属性占位符的动态解析结果的文本文字的实际值为零,由于@EnabledIf(“ false”)
等效于@Disabled
,而@EnabledIf(“ true”)
在逻辑上是没有意义的。
你可使用@EnabledIf
做为元注解来建立自定义的组合注释。例如,你能够建立一个自定义@EnabledOnMac
注解,以下所示:
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @EnabledIf( expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}", reason = "Enabled on Mac OS" ) public @interface EnabledOnMac {}
@DisabledIf
@DisabledIf
用于表示已注解的JUnit Jupiter测试类或测试方法被禁用,而且若是提供的表达式的值为true
,则不该执行该操做。具体来讲,若是表达式的计算结果为Boolean.TRUE
或等于true的字符串(忽略大小写),则测试将被禁用。当在类级别应用时,该类中的全部测试方法也会自动禁止。
表达式能够是如下任意一种:
@DisabledIf("#{systemProperties['os.name'].toLowerCase().contains('mac')}")
@DisabledIf("${smoke.tests.disabled}")
@DisabledIf("true")
可是请注意,不是属性占位符的动态解析结果的文本文字的实际值为零,由于@DisabledIf(“ true”
)等效于@Disabled
,而@DisabledIf(“ false”)
在逻辑上是没有意义的。
你能够将@DisabledIf
用做元注释,以建立自定义的组合注解。例如,你能够建立一个自定义@DisabledOnMac
注解,以下所示:
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @DisabledIf( expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}", reason = "Disabled on Mac OS" ) public @interface DisabledOnMac {}
你能够将大多数与测试相关的注解用做元注解,以建立自定义的组合注解,并减小整个测试套件中的重复配置。
你能够将如下各项用做与TestContext框架结合使用的元注解。
@BootstrapWith
@ContextConfiguration
@ContextHierarchy
@ActiveProfiles
@TestPropertySource
@DirtiesContext
@WebAppConfiguration
@TestExecutionListeners
@Transactional
@BeforeTransaction
@AfterTransaction
@Commit
@Rollback
@Sql
@SqlConfig
@SqlMergeMode
@SqlGroup
@Repeat
(仅支持 JUnit 4)@Timed
(仅支持 JUnit 4)@IfProfileValue
(仅支持 JUnit 4)@ProfileValueSourceConfiguration
(仅支持 JUnit 4)@SpringJUnitConfig
(仅支持 JUnit Jupiter)@SpringJUnitWebConfig
(仅支持JUnit Jupiter)@TestConstructor
(仅支持 JUnit Jupiter)@EnabledIf
(仅支持 JUnit Jupiter)@DisabledIf
(仅支持 JUnit Jupiter)考虑如下示例:
@RunWith(SpringRunner.class) @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) @ActiveProfiles("dev") @Transactional public class OrderRepositoryTests { } @RunWith(SpringRunner.class) @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) @ActiveProfiles("dev") @Transactional public class UserRepositoryTests { }
若是发现咱们要在基于JUnit 4的测试套件中重复上述配置,则能够经过引入一个自定义的组合注解来减小重复,该注解集中了Spring的通用测试配置,以下所示:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) @ActiveProfiles("dev") @Transactional public @interface TransactionalDevTestConfig { }
而后,咱们可使用咱们的自定义@TransactionalDevTestConfig
的注解来简化单个基于JUnit 4的测试类的配置,以下所示:
@RunWith(SpringRunner.class) @TransactionalDevTestConfig public class OrderRepositoryTests { } @RunWith(SpringRunner.class) @TransactionalDevTestConfig public class UserRepositoryTests { }
若是咱们编写使用JUnit Jupiter的测试,则能够进一步减小代码重复,由于JUnit 5中的注解也能够用做元注解。考虑如下示例:
@ExtendWith(SpringExtension.class) @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) @ActiveProfiles("dev") @Transactional class OrderRepositoryTests { } @ExtendWith(SpringExtension.class) @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) @ActiveProfiles("dev") @Transactional class UserRepositoryTests { }
若是发现咱们在基于JUnit Jupiter的测试套件中重复了前面的配置,则能够经过引入一个自定义组合注解来减小重复,该注解集中了Spring和JUnit Jupiter的通用测试配置,以下所示:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(SpringExtension.class) @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) @ActiveProfiles("dev") @Transactional public @interface TransactionalDevTestConfig { }
而后,咱们可使用咱们的自定义@TransactionalDevTestConfig
的注解来简化基于单个JUnit Jupiter的测试类的配置,以下所示:
@TransactionalDevTestConfig class OrderRepositoryTests { } @TransactionalDevTestConfig class UserRepositoryTests { }
因为JUnit Jupiter支持使用@Test
、@RepeatedTest
、ParameterizedTest
和其余做为元注解,所以你也能够在测试方法级别建立自定义的组合注解。例如,若是咱们但愿建立一个组合的注解,将JUnit Jupiter的@Test
和@Tag
注解与Spring的@Transactional
注解相结合,则能够建立一个@TransactionalIntegrationTest
注解,以下所示:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Transactional @Tag("integration-test") // org.junit.jupiter.api.Tag @Test // org.junit.jupiter.api.Test public @interface TransactionalIntegrationTest { }
而后,咱们可使用自定义的@TransactionalIntegrationTest
注解来简化基于单个JUnit Jupiter的测试方法的配置,以下所示:
@TransactionalIntegrationTest void saveOrder() { } @TransactionalIntegrationTest void deleteOrder() { }
有关更多详细信息,请参见Spring Annotation编程模型Wiki页。
我的从事金融行业,就任过易极付、思建科技、某网约车平台等重庆一流技术团队,目前就任于某银行负责统一支付系统建设。自身对金融行业有强烈的爱好。同时也实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域。同时也热衷于技术分享创立公众号和博客站点对知识体系进行分享。关注公众号: 青年IT男 获取最新技术文章推送!
博客地址: http://youngitman.tech
CSDN: https://blog.csdn.net/liyong1...
微信公众号:
技术交流群: