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源码