将 jUnit 超时与 @DirtiesContext 相结合
Combine jUnit timeout with @DirtiesContext
我有一个测试用例可以修改我的 spring 上下文,并且可能 运行 进入无限循环。在测试用例之后,我想要一个干净的 spring 上下文,所以我使用了 @DirtiesContext
注释。在无限循环的情况下,我添加了一个 jUnit 超时。
@Test(timeout = 1000)
@DirtiesContext
public void testTimeout() {
//test stuff
}
问题是,如果测试 运行 超时,jUnit 似乎会以 spring 不再处理上下文重置的方式终止它。如果我在 class 级别上添加 @DirtiesContext
,则行为相同。
还有其他方法可以实现我想要做的事情吗?
我设法解决了我的问题。我将 spring 升级到 4.2.0,它已经发布了大约一周,它支持在方法之前清理上下文。
@Test(timeout = 1000)
@DirtiesContext(methodMode = MethodMode.BEFORE_METHOD)
public void testTimeout() {
//test stuff
}
这样测试仍然会在超时后终止,但上下文会在下一个方法之前被清除。猜想这样我每次测试都有一个不必要的上下文初始化 class 但它有效。
要使用 JUnit 和 Spring TestContext Framework (TCF) 配置 timeout,您有两个主要类别选项:
- preemptive:如果您使用 JUnit 的
Timeout
规则或 @Test
的 timeout
属性,您的测试和所有嵌套规则,关联before/after 方法、TCF 回调等将在单独的线程中执行,如果 timeout 已超出。
- 非抢占式:如果您将 Spring 的
@Timed
注释与 TCF 一起使用,您的测试和所有嵌套规则,关联 before/after 方法、TCF 回调等将在与测试运行器相同的线程中执行,测试只有在正常终止且超时 已超过。
Timeout
规则和 @Test
的 timeout
属性都会导致在幕后使用 FailOnTimeout
语句; FailOnTimeout
在一个单独的线程中执行链中的下一条语句,如果超过超时,该线程将被抢先终止。因此,这两个基于 JUnit 的配置选项的行为自然是相同的:语句链的执行提前结束,没有给任何 after 回调执行其任务的机会。结果是 Spring 的 DirtiesContextTestExecutionListener
中的 afterTestMethod() 回调在这种情况下永远不会被调用,因此上下文不会是 脏.
Is there another way to achieve what I'm trying to do?
对于初学者,使用 Spring 的 @Timed
注释不适合您,因为它不会抢先中止在无限循环中运行的代码。
您提到您通过使用 Spring Framework 4.2 中引入的 @DirtiesContext(methodMode = BEFORE_METHOD)
功能发现了一个解决方法。 可能在某些情况下工作,但这种变通办法充其量是脆弱的:使用这种变通办法会导致上下文在[=63=之前关闭并重新启动] 这个 特定的方法;但是,如果有问题的代码在抢占式超时之前修改了上下文,您的 Spring 上下文对于后续测试方法将保持损坏。
唯一真正的解决方案是确保在next上使用@DirtiesContext
和BEFORE_METHOD
模式] 方法 在 由于超时而被抢先中止的方法之后执行。然而...确切知道哪种方法是 "next" 方法可能是具有挑战性的部分...除非您使用 JUnit 的 @FixMethodOrder
支持。
此致,
Sam(Spring TestContext Framework 的作者)
我有一个测试用例可以修改我的 spring 上下文,并且可能 运行 进入无限循环。在测试用例之后,我想要一个干净的 spring 上下文,所以我使用了 @DirtiesContext
注释。在无限循环的情况下,我添加了一个 jUnit 超时。
@Test(timeout = 1000)
@DirtiesContext
public void testTimeout() {
//test stuff
}
问题是,如果测试 运行 超时,jUnit 似乎会以 spring 不再处理上下文重置的方式终止它。如果我在 class 级别上添加 @DirtiesContext
,则行为相同。
还有其他方法可以实现我想要做的事情吗?
我设法解决了我的问题。我将 spring 升级到 4.2.0,它已经发布了大约一周,它支持在方法之前清理上下文。
@Test(timeout = 1000)
@DirtiesContext(methodMode = MethodMode.BEFORE_METHOD)
public void testTimeout() {
//test stuff
}
这样测试仍然会在超时后终止,但上下文会在下一个方法之前被清除。猜想这样我每次测试都有一个不必要的上下文初始化 class 但它有效。
要使用 JUnit 和 Spring TestContext Framework (TCF) 配置 timeout,您有两个主要类别选项:
- preemptive:如果您使用 JUnit 的
Timeout
规则或@Test
的timeout
属性,您的测试和所有嵌套规则,关联before/after 方法、TCF 回调等将在单独的线程中执行,如果 timeout 已超出。 - 非抢占式:如果您将 Spring 的
@Timed
注释与 TCF 一起使用,您的测试和所有嵌套规则,关联 before/after 方法、TCF 回调等将在与测试运行器相同的线程中执行,测试只有在正常终止且超时 已超过。
Timeout
规则和 @Test
的 timeout
属性都会导致在幕后使用 FailOnTimeout
语句; FailOnTimeout
在一个单独的线程中执行链中的下一条语句,如果超过超时,该线程将被抢先终止。因此,这两个基于 JUnit 的配置选项的行为自然是相同的:语句链的执行提前结束,没有给任何 after 回调执行其任务的机会。结果是 Spring 的 DirtiesContextTestExecutionListener
中的 afterTestMethod() 回调在这种情况下永远不会被调用,因此上下文不会是 脏.
Is there another way to achieve what I'm trying to do?
对于初学者,使用 Spring 的 @Timed
注释不适合您,因为它不会抢先中止在无限循环中运行的代码。
您提到您通过使用 Spring Framework 4.2 中引入的 @DirtiesContext(methodMode = BEFORE_METHOD)
功能发现了一个解决方法。 可能在某些情况下工作,但这种变通办法充其量是脆弱的:使用这种变通办法会导致上下文在[=63=之前关闭并重新启动] 这个 特定的方法;但是,如果有问题的代码在抢占式超时之前修改了上下文,您的 Spring 上下文对于后续测试方法将保持损坏。
唯一真正的解决方案是确保在next上使用@DirtiesContext
和BEFORE_METHOD
模式] 方法 在 由于超时而被抢先中止的方法之后执行。然而...确切知道哪种方法是 "next" 方法可能是具有挑战性的部分...除非您使用 JUnit 的 @FixMethodOrder
支持。
此致,
Sam(Spring TestContext Framework 的作者)