Java 合并来自不同声明的多个@TestExecutionListener?
对于我的SpringBoot应用程序的集成测试,我声明了自定义元注释(有点像SpringBoot的测试片注释)。如何在每个元注释中声明不同的TestExecutionListener,并在运行测试类时将它们合并 我只能找到Java 合并来自不同声明的多个@TestExecutionListener?,java,spring,spring-boot,spring-test,spring-boot-test,Java,Spring,Spring Boot,Spring Test,Spring Boot Test,对于我的SpringBoot应用程序的集成测试,我声明了自定义元注释(有点像SpringBoot的测试片注释)。如何在每个元注释中声明不同的TestExecutionListener,并在运行测试类时将它们合并 我只能找到mergeMode=MERGE_WITH_DEFAULTS,它将声明的TestExecutionListener与默认的Listener合并,但不能在不同的位置声明不同的自定义侦听器 一个简单的例子: @Target(ElementType.TYPE) @Retention(R
mergeMode=MERGE_WITH_DEFAULTS
,它将声明的TestExecutionListener与默认的Listener合并,但不能在不同的位置声明不同的自定义侦听器
一个简单的例子:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@TestExecutionListeners(
listeners = DbTestListener.class,
mergeMode = MERGE_WITH_DEFAULTS)
public @interface DbIntegrationTest {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@TestExecutionListeners(
listeners = MessagingTestListener.class,
mergeMode = MERGE_WITH_DEFAULTS)
public @interface MessagingIntegrationTest {
}
@RunWith(SpringRunner.class)
@DbIntegrationTest
@MessagingIntegrationTest
public class ExampleTest {
// test cases here
}
因此,我希望为我的ExampleTest
执行定制的TestListener和默认的TestListener
澄清:上面的例子是最小的,以显示我想要什么。当然,这样做没有多大意义。我自己编写的注释中有很多我没有展示的设置,我有多层元注释。这些侦听器做什么?若提供了执行环境,那个么您就误用了侦听器API 要配置(和清理)环境,您应该使用
\@Rule
如果使用Junit4@ClassRule
如果使用Junit5@ExtendWith
这些功能很容易在单个测试中组合。当前版本的spring测试中没有此类功能 如果你更深入地思考你的想法,在某些情况下会引入模棱两可的概念。例如,如果
@DbIntegrationTest
和@messaginintegrationtest
配置了不同的合并模式
或继承侦听器
,框架应该使用哪个值
当前的行为是,如果有多个@TestExecutionListeners
或其元注释被标记,则只有最前面声明的一个将生效,而另一个将被忽略
一些可能帮助您实现类似结果的想法:
TestExecutionListeners
分组,这些将在不同的测试场景中一起使用。只需将这个元注释注释到测试类。例如:@MessagingTest
包含消息传递集成测试所需的所有侦听器:
@TestExecutionListeners(
侦听器={SetupMessageBrokerListener.class,FooBarListener.class},
mergeMode=将\u与\u默认值合并)
公共@interface MessagingTest{
}
@DatabaseTest
包含DB集成测试所需的所有侦听器:
@TestExecutionListeners(
侦听器={SetupDatabaseListener.class,CreateTestingDataListener.class,FooBarListener.class},
mergeMode=将\u与\u默认值合并)
public@interface数据库测试{
}
TestContextBootstrapper
。要创建的TestExecutionListener
在其getTestExecutionListeners()
中定义。使用@BootstrapWith
激活此TestContextBootstrapper
<代码>AbstractTestContextBootstrapper是一个很好的起点。基本上,您需要在getTestExecutionListeners()
的末尾添加自定义逻辑。遗憾的是,此方法已完成,不允许在子类中重写一种可能的解决方案是在META-INF/spring.Factorys中注册所有TestExecutionListeners,并编写每个侦听器,以便仅当测试类或测试上下文中存在某个注释(或其他标记)时,它才执行某些操作 有关spring.factories的用法,请参见:
此解决方案的缺点是TestExecutionListeners(已定义且将处于活动状态)的设置有点“隐藏”或分散在代码库中。它们对测试环境进行准备和/或后处理。DbListener(例如)在每次测试前清除数据库。它们是Spring的测试框架独立测试支持的一个组成部分,请参见:至于为什么不使用例如
@Rule
:正如我在示例中所示,@TestExecutionListeners
注释可以用作元注释(即在组合注释中)。使用@Rule
等,我必须将规则添加到每个测试类中。使用我的@DbIntegrationTest
组合注释,我可以将该注释放在类的顶部,然后从那里处理所有事情(测试设置的内聚性)。此外,Spring TestExecutionListeners可以访问Spring的测试上下文,这可能很有用。老实说,我看不出@ClassRule
和元注释在您的情况下有什么区别:元注释应该在每个测试中添加一次(“在我的类的顶部”),而@ClassRule
应该在每个测试中添加一次(“我必须将规则添加到每个测试类中”)。无论如何,我只能建议您尝试最新的Spring框架-可能是他们改进了它,如果他们没有改进,那么您可以在他们的Github中归档错误。或者,您可以为每个有意义的侦听器组合创建元注释,即@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@TestExecutionListeners(listeners={DbTestListener.class,MessagingTestListener.class},mergeMode=MERGE_WITH_DEFAULTS)public@interface Database和MessagingIntegrationTest{}
很好的尝试,应该可以。在这种情况下,您必须重写GetDefaultTestExecutionListenerClass()DefaultTestContextBootstrapper的
,并将这些逻辑添加到其中。不,实际上我认为标准引导程序已经做到了。Spring文档明确地说:第三方框架和开发人员可以通过自己的META-INF/spring.factories属性文件,以同样的方式将自己的TestExecutionListener实现贡献给默认侦听器列表