注册拓展
可以通过@ExtendWith以声明方式注册,可以通过@RegisterExtension以编程方式注册,也可以通过Java的ServiceLoader机制自动注册。
声明扩展注册
开发人员可以通过使用 @ExtendWith(…)
对测试接口、测试类、测试方法或自定义组合注释进行声明式注册一个或多个扩展,并为要注册的扩展提供类引用。
- 指定单个方法
例如,要为一个特定的测试方法注册一个自定义的 RandomParametersExtension,您可以按照以下方式注释这个测试方法。
@ExtendWith(RandomParametersExtension.class)
@Test
void test(@Random int i) {
// ...
}
- 指定整个类
要为一个特定类及其子类中的所有测试注册一个定制的RandomParametersExtension,您可以按照以下方式注释这个测试类。
@ExtendWith(RandomParametersExtension.class)
class MyTests {
// ...
}
- 多个扩展
@ExtendWith({ FooExtension.class, BarExtension.class })
class MyFirstTests {
// ...
}
作为替代方案,多个扩展可以像这样分别注册:
@ExtendWith(FooExtension.class)
@ExtendWith(BarExtension.class)
class MySecondTests {
// ...
}
扩展登记顺序
通过@ExtendWith以声明的方式注册的扩展将按照在源代码中声明的顺序执行。
例如,MyFirstTests和MySecondTests中的测试执行都将由FooExtension和BarExtension扩展,其顺序完全相同。
编程扩展注册
开发人员可以通过使用 @RegisterExtension
在测试类中注释字段来以编程方式注册扩展。
当扩展通过@ExtendWith以声明的方式注册时,通常只能通过注解进行配置。 相反,当扩展通过@RegisterExtension注册时,可以通过编程方式配置它——例如,为了将参数传递给扩展的构造函数、静态工厂方法或构建器API。
注意
@RegisterExtension 字段不能是 private 或 null(在评估时),但是可以是静态的,也可以是非静态的。
静态字段
如果@RegisterExtension字段是静态的,那么扩展将在通过@ExtendWith在类级注册的扩展之后被注册。
这种静态扩展并不局限于它们可以实现的扩展api。
因此,通过静态字段注册的扩展可以实现类级和实例级扩展api,如BeforeAllCallback、AfterAllCallback、TestInstancePostProcessor以及方法级扩展api,如BeforeEachCallback等。
在下面的示例中,通过使用WebServerExtension支持的构建器模式以编程方式初始化测试类中的服务器字段。
配置好的WebServerExtension将被自动注册为类级别的扩展——例如,为了在类中的所有测试之前启动服务器,然后在类中的所有测试完成之后停止服务器。
此外,使用@BeforeAll或@AfterAll注释的静态生命周期方法以及@BeforeEach、@AfterEach和@Test方法可以在必要时通过服务器字段访问扩展的实例。
class WebServerDemo {
@RegisterExtension
static WebServerExtension server = WebServerExtension.builder()
.enableSecurity(false)
.build();
@Test
void getProductList() {
WebClient webClient = new WebClient();
String serverUrl = server.getServerUrl();
// Use WebClient to connect to web server using serverUrl and verify response
assertEquals(200, webClient.get(serverUrl + "/products").getResponseStatus());
}
}
实例化字段(Instance Fields)
如果@RegisterExtension字段是非静态的(例如。在测试类被实例化后,在每个注册的TestInstancePostProcessor有机会对测试实例进行后处理之后(潜在地将扩展的实例注入到带注释的字段中),扩展将被注册。
因此,如果这样的实例扩展实现了类级或实例级的扩展api,比如BeforeAllCallback、AfterAllCallback或TestInstancePostProcessor,那么这些api就不会受到重视。
默认情况下,实例扩展将在通过@ExtendWith在方法级别注册的扩展之后注册;
但是,如果测试类配置为 @TestInstance(Lifecycle.PER_CLASS)
语义,则在通过@ExtendWith在方法级注册的扩展名之前注册一个实例扩展名。
在下面的示例中,通过调用自定义lookUpDocsDir()方法并将结果提供给DocumentationExtension中的静态forPath() factory方法,以编程方式初始化测试类中的docs字段。配置的DocumentationExtension将被自动注册为方法级别的扩展。此外,如果需要,@BeforeEach、@AfterEach和@Test方法可以通过docs字段访问扩展的实例。
- DocumentationDemo.java
class DocumentationDemo {
static Path lookUpDocsDir() {
// return path to docs dir
}
@RegisterExtension
DocumentationExtension docs = DocumentationExtension.forPath(lookUpDocsDir());
@Test
void generateDocumentation() {
// use this.docs ...
}
}
自动扩展注册
除了使用注释声明扩展注册和编程扩展注册支持之外,JUnit Jupiter还通过Java的 java.util.ServiceLoader
机制支持全局扩展注册。
允许根据类路径中可用的内容自动检测和自动注册第三方扩展。
具体地说,可以通过在一个名为 org.junit.jupiter.api.extension.Extension
的文件中提供其完全限定的类名来注册一个自定义扩展。
扩展名在 /META-INF/services 文件夹中,在它所包含的JAR文件中。
开启自动扩展注册
自动检测是一个高级功能,因此默认情况下不启用。要启用它,只需设置 junit.jupiter.extensions.autodetection.enabled
启用配置参数为true。
可以将其作为JVM系统属性提供,作为传递给启动程序的LauncherDiscoveryRequest中的配置参数,或者通过JUnit平台配置文件(详细信息请参见配置参数)。
例如,要启用扩展的自动检测,可以使用以下系统属性启动JVM。
-Djunit.jupiter.extensions.autodetection.enabled = true
当启用自动检测时,通过ServiceLoader机制发现的扩展将在JUnit Jupiter的全局扩展(例如,对TestInfo、TestReporter等的支持)之后添加到扩展注册表中。
扩展继承
通过自顶向下的语义在测试类层次结构中继承已注册的扩展。 类似地,在类级注册的扩展在方法级继承。 此外,特定的扩展实现只能为给定的扩展上下文及其父上下文注册一次。
因此,任何注册重复扩展实现的尝试都将被忽略。