Java JUnit tearDown()在我的测试完成之前完成执行(使用自定义运行程序)
JUnit@AfterClass方法在my@Tests(自定义运行程序)之前完成执行 我正在尝试制作我自己的JUnit测试运行程序。每次执行@AfterClass注释的方法时,我都想做一些事情。根据JUnit文档,@AfterClass方法应该在所有测试运行之后开始执行 我浏览了google,彻底使用了JUnit文档,阅读了 StackOverflow上的JUnit执行顺序等,但我似乎找不到任何其他发生这种情况的例子(可能是线程问题)。我发现了一个Spring使用自己的runner的例子,但它并没有帮助我解决这个问题Java JUnit tearDown()在我的测试完成之前完成执行(使用自定义运行程序),java,multithreading,junit,jira-rest-java-api,Java,Multithreading,Junit,Jira Rest Java Api,JUnit@AfterClass方法在my@Tests(自定义运行程序)之前完成执行 我正在尝试制作我自己的JUnit测试运行程序。每次执行@AfterClass注释的方法时,我都想做一些事情。根据JUnit文档,@AfterClass方法应该在所有测试运行之后开始执行 我浏览了google,彻底使用了JUnit文档,阅读了 StackOverflow上的JUnit执行顺序等,但我似乎找不到任何其他发生这种情况的例子(可能是线程问题)。我发现了一个Spring使用自己的runner的例子,但它并
public class CustomRunner extends BlockJUnit4ClassRunner {
public CustomRunner (Class<?> klass) throws InitializationError {
super(klass);
}
@Override
protected Statement withAfterClasses(Statement statement) {
Statement s = super.withAfterClasses(statement);
System.out.println("tearDown() executed!");
return s;
}
}
使用CustomRunner:
public class TestBugReporter0 {
@Before
public void setUp() {}
@Test
public void testAssertionFailure() {
assertEquals(3, 2);
}
@AfterClass
public static void tearDown() {
System.out.println("tearDown() executed!");
}
}
@RunWith(CustomRunner.class)
public class TestBugReporter1 {
@Before
public void setUp() {}
@Test
public void testAssertionFailure() {
assertEquals(3, 2);
}
@AfterClass
public static void tearDown() {}
}
TestBugReporter0始终打印以下内容:
setUp() executed!
java.lang.AssertionError: Expected :3, Actual :2
tearDown() executed!
然而,TestBugReporter1不是确定性的。跑了20次后,我总是得到以下三分之一
tearDown() executed!
setUp() executed!
java.lang.AssertionError: Expected :3, Actual :2
java.lang.AssertionError: Expected :3, Actual :2
tearDown() executed!
setUp() executed!
setUp() executed!
java.lang.AssertionError: Expected :3, Actual :2
tearDown() executed!
我认为这是一个线程问题,因为:
注意:TestNG有一个单线程配置,但我们现有的测试套件是纯JUnit,因此它不是一个选项。方法
和AfterClass
(以及以和开头的任何其他方法)不从测试类执行任何操作。相反,它们构建了一个语句
对象链,表示稍后将执行的内容
语句
:
表示在执行过程中运行时要执行的一个或多个操作
运行JUnit测试套件
请看一看类runafter
,它是语句
的一个子类,由与afterclasses的默认实现返回
JUnit似乎可以在测试类生命周期的不同时间请求此语句
;但是,您不应该关心这一点-只需返回一个实例语句
。您可以将其视为命令模式
更新
标准的runafter
实现使得在调用@AfterClass
之前或在@AfterClass
方法之后很难进行子类化和操作,因此我前面的建议不容易实现
这是你可以做到的
CustomRunner:
public class TestBugReporter0 {
@Before
public void setUp() {}
@Test
public void testAssertionFailure() {
assertEquals(3, 2);
}
@AfterClass
public static void tearDown() {
System.out.println("tearDown() executed!");
}
}
@RunWith(CustomRunner.class)
public class TestBugReporter1 {
@Before
public void setUp() {}
@Test
public void testAssertionFailure() {
assertEquals(3, 2);
}
@AfterClass
public static void tearDown() {}
}
公共类CustomRunner扩展了BlockJUnit4ClassRunner{
公共CustomRunner(类klass)引发初始化错误{
超级(klass);;
}
@凌驾
带AfterClass的受保护语句(语句语句){
List after=getTestClass().getAnnotatedMethods(AfterClass.class);
语句=新CustomRunAfter(语句,After,null);
返回语句;
}
}
自定义RunAfter:
公共类CustomRunAfter扩展语句{
非公开最终报表fNext;
私有最终目标;
私人最终名单;
公共CustomRunAfter(下一个语句、列表After、对象目标){
fNext=下一个;
fAfters=after;
fTarget=目标;
}
@凌驾
public void evaluate()可丢弃{
List fErrors=新的ArrayList();
弗罗尔斯。克利尔();
试一试{
fNext.evaluate();
}捕获(可丢弃的e){
添加(e);
}最后{
beforetrunafter();
对于(每个框架方法:fAfters){
试一试{
each.invokeeexplosive(fTarget);
}捕获(可丢弃的e){
添加(e);
}
}
afterrunafter();
}
if(fErrors.isEmpty())
返回;
如果(fErrors.size()==1)
抛出fErrors.get(0);
抛出新的MultipleFailureException(fErrors);
}
私有无效后运行(){
System.err.println(“在运行@AfterClass方法之后”);
}
运行之前的私有无效(){
System.err.println(“在运行@AfterClass方法之前”);
}
}
在上面的代码中,您可以在beforeRunAfter
和afterRunAfter
方法中执行自定义操作
注意:上面的代码片段包含JUnit4.5中修改过的源代码。在必要的情况下,我在此使用与JUnit(Eclipse公共许可证)等相同的许可证对我的修改进行许可。处理顺序正确
问题是输出。
输出将写入System.out,而断言错误将使用System.err打印
它们的输出顺序不一定正确
另见
我认为这不是本例中的问题,因为输出不是确定性的。为什么不试试?JUnit可以在它喜欢的任何时间点用AfterClass调用,
,因为它实际上并没有执行任何代码;相反,它是建立一个声明性的动作链,稍后再执行。是的,你是对的。但是,代码片段并不一致。TestBugReporter0类包含@AfterMethod中的输出以及CustomRunner中的方法