2.12、构造器和方法得依赖注入
在所有之前得JUnit版本,测试构造器或者测试方法是不允许含有参数(至少在标准得Runner实现上是不允许得)。作为JUnit Jupiter得一个大改变来说,构造方法和方法现在可以有参数。构造器和方法允许依赖注入带来了很大得灵活性。
ParameterResolver是为了在运行时动态解析参数的测试扩展定义了API。如果一个测试类得构造器、测试方法或者生命周期方法接收参数,这个参数一定会在被注册得ParameterResolver来解析得。
现在有三个内置得解析器会被自动注册。
TestInfoOarameterResolver:如果一个构造器和方法参数是TestInfo类型,TestInfoParameterResolver将提供与当前容器或测试相对应地TestInfo实例。然后可以使用TestInfo来检索关于当前容器或测试的信息,例如显示名称、测试类、测试方法和相关标记。显示名称可以是技术名称,例如测试类或测试方法的名称,也可以是通过@DisplayName配置的自定义名称。TestInfo充当JUnit 4中的TestName规则的替代。下面代码演示了如何将TestInfo注入到测试构造器、@BeforeEach方法和@Test方法。import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; @DisplayName("TestInfo Demo") class TestInfoDemo { TestInfoDemo(TestInfo testInfo) { assertEquals("TestInfo Demo", testInfo.getDisplayName()); } @BeforeEach void init(TestInfo testInfo) { String displayName = testInfo.getDisplayName(); assertTrue(displayName.equals("TEST 1") || displayName.equals("test2()")); } @Test @DisplayName("TEST 1") @Tag("my-tag") void test1(TestInfo testInfo) { assertEquals("TEST 1", testInfo.getDisplayName()); assertTrue(testInfo.getTags().contains("my-tag")); } @Test void test2() { } }RepetitionInfoParameterResolver:如果方法是用@RepeatedTest、@BeforeEach和@AfterEach标志,且其参数是RepetitionInfo类型,RepetitionInfoParameterResolver会提供一个RepetitionInfo实例。RepetitionInfo甚至可以用来获取当前对应@RepeatedTest方法地重复测试信息和重复测试地总次数。注意:RepetitionInfoParameterResolver并不会在@RepeatedTest上下文中注册。TestReporterParameterResolver:如果一个构造器和方法参数是TestReporter类型,TestReporterParameterResolver将会提供TestReporter实例。TestReporter可以被用来关于当前测试运行时地额外信息。这些数据会在TestExecutionListener的reportingEntryPublished()方法使用,也可以在IDE或者报告中查看到这些信息。在
JUnit4中使用stout和stderr输出信息,而在JUnit Jupiter使用TestReporter。使用@RunWith(JUnitPlatform.class)将会输出所有信息到stdout。而且,有些ide打印报告条目以输出标准输出,或者在用户界面中显示它们以获得测试结果。class TestReporterDemo { @Test void reportSingleValue(TestReporter testReporter) { testReporter.publishEntry("a status message"); } @Test void reportKeyValuePair(TestReporter testReporter) { testReporter.publishEntry("a key", "a value"); } @Test void reportMultipleKeyValuePairs(TestReporter testReporter) { Map<String, String> values = new HashMap<>(); values.put("user name", "dk38"); values.put("award year", "1974"); testReporter.publishEntry(values); } }要是想使用其他参数解析器,必须通过
@ExtendWith注册适当的扩展显式地启用。
使用RandomParametersExtension作为自定义的ParameterResolver的一个例子。虽然不打算用于生产,但它演示了扩展模型和参数解析过程的简单性和表达性。MyRandomParametersTest展示了如何向@Test方法中注入一个随机值。
@ExtendWith(RandomParametersExtension.class)
class MyRandomParametersTest {
@Test
void injectsInteger(@Random int i, @Random int j) {
assertNotEquals(i, j);
}
@Test
void injectsDouble(@Random double d) {
assertEquals(0.0, d, 1.0);
}
}
在真实使用的时候,请参考MockitoExtension源码和SpringExtension源码