JUNIT 5:将 spring 组件注入自定义 TestTemplateInvocationContextProvider

JUNIT 5: Inject spring components to custom TestTemplateInvocationContextProvider

JUnit Jupiter (JUnit 5) 中是否有一种方法可以将 Spring 组件注入 TestTemplateInvocationContextProvider

是的,如果您在为测试 class 加载的 Spring ApplicationContext 中将您的 TestTemplateInvocationContextProvider 注册为 bean,然后您可以让提供程序 @Autowired 到一个字段中,并使用 @RegisterExtension 注册为 JUnit Jupiter 扩展。诀窍是您需要使用每个 class 测试实例生命周期模式,以便提早注册提供者以便 JUnit Jupiter 使用它。

以下是 JUnit 5 用户指南中 TestTemplateDemo 的修改版本。

测试通过 "as is",但您可以从 @Bean 声明中删除 baz bean 的 // 以查看测试失败。

@SpringJUnitConfig
@TestInstance(Lifecycle.PER_CLASS)
class TestTemplateDemo {

    @Autowired
    @RegisterExtension
    TestTemplateInvocationContextProvider testTemplateInvocationContextProvider;

    @TestTemplate
    void testTemplate(String parameter) {
        assertTrue("foo".equals(parameter) || "bar".equals(parameter));
    }

    @Configuration
    static class Config {

        @Bean
        String foo() {
            return "foo";
        }

        @Bean
        String bar() {
            return "bar";
        }

        // @Bean
        String baz() {
            return "baz";
        }

        @Bean
        TestTemplateInvocationContextProvider myTestTemplateInvocationContextProvider(
                List<String> parameters) {

            return new MyTestTemplateInvocationContextProvider(parameters);
        }
    }

    public static class MyTestTemplateInvocationContextProvider
            implements TestTemplateInvocationContextProvider {

        private final List<String> parameters;

        public MyTestTemplateInvocationContextProvider(List<String> parameters) {
            this.parameters = parameters;
        }

        @Override
        public boolean supportsTestTemplate(ExtensionContext context) {
            return true;
        }

        @Override
        public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(
                ExtensionContext context) {

            return this.parameters.stream().map(p -> invocationContext(p));
        }

        private TestTemplateInvocationContext invocationContext(String parameter) {
            return new TestTemplateInvocationContext() {

                @Override
                public String getDisplayName(int invocationIndex) {
                    return parameter;
                }

                @Override
                public List<Extension> getAdditionalExtensions() {
                    return Collections.singletonList(new ParameterResolver() {

                        @Override
                        public boolean supportsParameter(
                                ParameterContext parameterContext,
                                ExtensionContext extensionContext) {
                            return parameterContext.getParameter().getType().equals(
                                    String.class);
                        }

                        @Override
                        public Object resolveParameter(ParameterContext parameterContext,
                                ExtensionContext extensionContext) {
                            return parameter;
                        }
                    });
                }
            };
        }
    }

}