Java 在测试类之前和之后使ApplicationContext变脏

Java 在测试类之前和之后使ApplicationContext变脏,java,spring,spring-test,Java,Spring,Spring Test,在Spring集成测试中,我有一个特定的类(比如说MyTest),它在Spring组件上使用PowerMock@PrepareForTest注释:@PrepareForTest(MyComponent.class)。这意味着PowerMock将通过一些修改加载此类。问题是,我的@ContextConfiguration是在超类上定义的,超类由MyTest扩展,ApplicationContext在不同的测试类之间缓存。现在,如果首先运行MyTest,它将拥有正确的PowerMock版本的MyCo

在Spring集成测试中,我有一个特定的类(比如说
MyTest
),它在Spring组件上使用PowerMock
@PrepareForTest
注释:
@PrepareForTest(MyComponent.class)
。这意味着PowerMock将通过一些修改加载此类。问题是,我的
@ContextConfiguration
是在超类上定义的,超类由
MyTest
扩展,
ApplicationContext
在不同的测试类之间缓存。现在,如果首先运行
MyTest
,它将拥有正确的PowerMock版本的
MyComponent
,但如果没有,测试将失败,因为将为另一个测试加载上下文(没有@PrepareForTest)

所以我想做的是在
MyTest
之前重新加载上下文。我可以通过

@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
但如果我还想在测试完成后重新加载上下文呢?因此,我将再次使用干净的
MyComponent
,而无需进行PowerMock修改。有没有一种方法既可以在课前做
,也可以在课后做

目前,我是通过以下方法完成的:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
在我的测试中,然后

/**
 * Stub test to reload ApplicationContext before execution of real test methods of this class.
 */
@DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
@Test
public void aa() {
}

/**
 * Stub test to reload ApplicationContext after execution of real test methods of this class.
 */
@DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD)
@Test
public void zz() {
}
我想知道有没有更漂亮的方法

作为一个附带问题,是否可以只重新加载特定的bean而不重新加载完整的上下文

课前和课后都有办法吗

不,很遗憾,
@DirtiesContext
不支持这一点

但是,您真正想说的是,您希望为
MyTest
创建一个新的
ApplicationContext
,它与父测试类的上下文相同,但只在
MyTest
期间有效。而且。。。您不希望影响为父测试类缓存的上下文

因此,考虑到这一点,下面的技巧应该可以做到这一点

@RunWith(SpringJUnit4ClassRunner.class)
//从父级继承配置并与本地
//创建新上下文的静态配置类
@上下文配置
@肮脏的环境
公共类MyTest扩展了BaseTests{
@配置
静态类配置{
//不需要定义任何实际的@Bean方法。
//我们只需要添加一个额外的@Configuration
//类,以便获得新的ApplicationContext。
}
}
可替代@DirtiesContext

如果您想在测试类之前和之后都弄脏上下文,您可以实现一个定制的
TestExecutionListener
,它正好做到这一点。例如,以下内容将实现此目的

import org.springframework.core.Ordered;
导入org.springframework.test.annotation.DirtiesContext.HierarchyMode;
导入org.springframework.test.context.TestContext;
导入org.springframework.test.context.support.AbstractTestExecutionListener;
公共类dirtyContextBefore和AfterClassTestExecutionListener
扩展AbstractTestExecutionListener{
@凌驾
public int getOrder(){
返回顺序。最高优先级;
}
@凌驾
public void beforeTestClass(TestContext TestContext)引发异常{
markApplicationContextDirty(HierarchyMode.definancial);
}
@凌驾
公共void后测试类(TestContext TestContext)引发异常{
markApplicationContextDirty(HierarchyMode.definancial);
}
}
然后可以在
MyTest
中使用自定义侦听器,如下所示

导入org.springframework.test.context.TestExecutionListeners;
导入org.springframework.test.context.TestExecutionListeners.MergeMode;
@TestExecutionListeners(
listeners=DirtyContextBefore和AfterClassTestExecutionListener.class,
mergeMode=mergeMode.MERGE_与_默认值
)
公共类MyTest扩展了BaseTest{/*…*/}
作为一个附带问题,是否可以只重新加载特定的bean而不重新加载完整的上下文

不,那也是不可能的

问候,


Sam(Spring TestContext Framework的作者)

为什么要在测试之前将上下文标记为脏的?正如前面所说的,我想为MyTest类重新加载上下文,这样我的@PrepareForTest(MyComponent.class)就可以了。谢谢你的回复
您希望MyTest的新应用程序上下文与父测试类的上下文相同
这不是真的,因为MyTest的上下文不会完全相同,因为它应该使用
@PrepareForTest(MyComponent.class)
。我试过你的建议,但遇到了另一个问题。据我所知,将有两个并行上下文,这在当前是不可能的(配置了一个Hazelcast实例,并且在一个端口上只能有一个)。我可以处理这个问题,所以我很好奇如何让我的Powemock注释在这个嵌套上下文上工作?我通过添加一个定制的
TestExecutionListener
更新了我的答案,它会在测试类之前和之后弄脏上下文。让我知道这是否解决了你的问题。是的,它确实解决了,而且看起来比黑客好多了:)谢谢@SamBrannen我是以这种方式实现的,在实现之后,我开始使用循环依赖语句获取beanInitializationException,如果我在子类中不使用侦听器,情况就不是这样了。在spring testing doc页面上,我看到了一些配置建议,如果我正在为一个测试套件进行配置,那么我的测试套件的一半也将使用这个监听器,o我需要在jar中放入一个文件spring.factory和自定义监听器项。@SamBrannen我以这种方式实现,在执行错误后,如果我不在我的子类中使用侦听器,情况就不是这样了。在SpringTestingDoc页面上,我看到了一些配置建议,如果我正在为一个测试套件进行配置,那么我的测试套件的一半都使用这个监听器,我是否需要在jar中放置一个带有自定义监听器条目的文件spring.factory。