Unit testing 我可以添加一个junit侦听器,它可以在测试类之间而不是在测试用例之间调用吗?
我遇到了一个问题,单元测试正在修改类Unit testing 我可以添加一个junit侦听器,它可以在测试类之间而不是在测试用例之间调用吗?,unit-testing,maven,junit,junit-runner,Unit Testing,Maven,Junit,Junit Runner,我遇到了一个问题,单元测试正在修改类Foo的静态状态,并且没有在完成之后进行清理。这意味着一个单元测试在自己运行时可能会通过,但在之前运行其他单元测试时可能会失败,因为状态已更改 我一直在浏览代码,寻找那些改变Foo静态的测试,并添加必要的清理,但后来我有了另一个想法:为什么不在每个测试运行后使用junit测试侦听器检查Foo的静态,如果Foo处于修改状态,那么测试就会失败?然后,我会自动获得每个构建的顽皮测试列表,并且可以在将来识别任何类似的问题 因此,我实现了一个junitRunListen
Foo
的静态状态,并且没有在完成之后进行清理。这意味着一个单元测试在自己运行时可能会通过,但在之前运行其他单元测试时可能会失败,因为状态已更改
我一直在浏览代码,寻找那些改变Foo
静态的测试,并添加必要的清理,但后来我有了另一个想法:为什么不在每个测试运行后使用junit测试侦听器检查Foo
的静态,如果Foo
处于修改状态,那么测试就会失败?然后,我会自动获得每个构建的顽皮测试列表,并且可以在将来识别任何类似的问题
因此,我实现了一个junitRunListener
,并修改了我的pom.xml
,将侦听器添加到maven surefire插件中,并验证了每个测试用例都执行了侦听器
简单的解决方案是重写RunListener
的testFinished()
方法并检查静态:
public class FooChecker extends RunListener {
@Override
public void testFinished(Description description) throws Exception {
if (fooClassInModifiedState()) {
throw new IllegalStateException("Test " + description.getDisplayName()
+ " has left Foo in a modified state");
}
}
}
这将适用于以下形式的测试:
public class SomeTest {
@Before
public void setUpTest() {
Foo.modifyState();
}
@After
public void tearDownTest() {
Foo.resetState();
}
@Test
public void testCase1() {
...
}
@Test
public void testCase2() {
...
}
}
在每个测试用例之后,调用@After
方法并清除状态。然后调用junit运行侦听器的testFinished()
方法,并验证状态是否已重置。如果我删除@After
方法,那么运行侦听器将引发一个错误,正如预期的那样
这里的问题是,junit运行侦听器的testFinished
方法是在单元测试的@BeforeClass
方法之后和任何@AfterClass
方法之前调用的。如果单元测试在@BeforeClass
中修改Foo的状态,并在@AfterClass
方法中进行清理,则侦听器的testFinished
方法将看到修改的状态并错误地引发错误:
public class SomeTest {
@BeforeClass
public void setUpClass() {
Foo.modifyState();
}
@Test
public void testCase1() {
...
}
@Test
public void testCase2() {
...
}
@AfterClass
public void tearDownClass() {
Foo.resetState();
}
}
这里,运行侦听器的testFinished()
方法在调用testCase1()
和testCase2()
之后调用,但在调用@AfterClass
方法之前调用,因此Foo
的状态仍然被修改,运行侦听器将引发错误。这不是正确的行为
通常,对于两个单元测试TestA
和TestB
,以及一个junit运行监听器监听器
,调用顺序似乎是:
- Listener.testRunStarted()
- 课前测试
- teststart(“TestA.testCase1”)
- 种皮
- TestA.testCase1()
- 种皮
- testFinished(TestA.testCase1)
- teststart(“TestA.testCase2”)
- 种皮
- TestA.testCase2()
- 种皮
- testFinished(TestA.testCase2)
- 外种皮
- TestB.@BeforeClass
- teststart(“TestB.testCase1”)
- TestB.@之前
- TestB.testCase1()
- TestB.@之后
- testFinished(TestB.testCase1)
- TestB.@AfterClass
- Listener.testRunFinished()
我希望在单元测试调用@AfterClass
方法之后,以及在下一个单元测试调用@BeforeClass
方法之前,执行修改状态检查。这样,我可以确保单元测试(如果不是单个测试用例的话)执行必要的清理,并且仍然尊重测试语义
但我看不到使用junitRunListener
和使用maven surefire插件调用测试的方法
这里有解决办法吗
编辑:将junit类规则添加到检查状态的现有测试中不是一个选项,因为我需要将它添加到现在存在的每个测试以及将来添加的每个测试中。如果可能的话,我希望能够自动发现任何违规行为
编辑:这里的根本问题是maven模块的每个单元测试都在同一个JVM中运行。我尝试在自己的JVM中运行每个单元测试(通过设置surefire的分叉选项),但测试运行时间太长。因此,我只能使用一个JVM进行多个单元测试
编辑:当然,首先使用静态方法是不好的设计,重构以注入状态将是首选,但在这个阶段重构1000000多行的遗留代码库不是一个选项。尝试testng相关资源:。这种技术可以为每个测试类“重置”静态类(但遗憾的是不是每个测试方法).您是否考虑过重构是否允许您在不调用(和更改)的情况下测试代码静态数据?您将花费大量精力来尝试和解决此问题,但在许多情况下,这可能是次要的。也许您可以分享您的类的一些详细信息,我们也可以在这方面提供建议?感谢关于重构的建议,但我还是更愿意重构代码以消除任何静态依赖,我担心这(出于各种原因)现在不是一个选项。每个单元测试单独的类加载器是一个好主意,但它意味着修改现有和未来的单元测试以使用特定的junit运行程序,而不是透明的进程,并且一些单元测试已经在使用其他junit运行程序(例如,使用PowerMock),所以不幸的是,我现在不认为这是一个选择。