为什么RunListener类testRunStarted()方法在JUnit中为单个测试多次调用?

时间:2017-12-10 15:19:03

标签: java junit

我已经尝试了github.com/bradmartin/nativescript-checkbox

中示例中给出的JUnit侦听器的示例

MyRunner.class

public class MyRunner extends BlockJUnit4ClassRunner {

public MyRunner(Class<?> klass) throws InitializationError {
    super(klass);
}

@Override public void run(RunNotifier notifier){
    notifier.addListener(new JUnitExecutionListener());
    notifier.fireTestRunStarted(getDescription());
    super.run(notifier);
}
}

JUnitExecutionListener.class

public class JUnitExecutionListener extends RunListener {

@Override
public void testRunStarted(Description description) throws Exception {
    System.out.println("Number of tests to execute: " + description.testCount());
}

@Override
public void testRunFinished(Result result) throws Exception {
    System.out.println("Number of tests executed: " + result.getRunCount());
}

@Override
public void testStarted(Description description) throws Exception {
    System.out.println("Starting: " + description.getMethodName());
}

@Override
public void testFinished(Description description) throws Exception {
    System.out.println("Finished: " + description.getMethodName());
}

@Override
public void testFailure(Failure failure) throws Exception {
    System.out.println("Failed: " + failure.getDescription().getMethodName());
}

@Override
public void testAssumptionFailure(Failure failure) {
    System.out.println("Failed: " + failure.getDescription().getMethodName());
}

@Override
public void testIgnored(Description description) throws Exception {
    System.out.println("Ignored: " + description.getMethodName());
}
}

我有3个测试,如下所示

Sample1Test.class

@RunWith(MyRunner.class)
public class Sample1Test {

@Test
public void step1() {
    System.out.println("Sample1Test step1");
}
}

Sample2Test.class

@RunWith(MyRunner.class)
public class Sample2Test {

@Test
public void step1() {
    System.out.println("Sample2Test step1");
}
}

Sample3Test.class

@RunWith(MyRunner.class)
public class Sample3Test {

@Test
public void step1() {
    System.out.println("Sample3Test step1");
}
}

在控制台上,我收到了以下日志,

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.demo.test.Sample1Test
Number of tests to execute: 1
Starting: step1
Sample1Test step1
Finished: step1
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.064 sec
Running com.demo.test.Sample2Test
Number of tests to execute: 1
Number of tests to execute: 1
Starting: step1
Starting: step1
Sample2Test step1
Finished: step1
Finished: step1
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
Running com.demo.test.Sample3Test
Number of tests to execute: 1
Number of tests to execute: 1
Number of tests to execute: 1
Starting: step1
Starting: step1
Starting: step1
Sample3Test step1
Finished: step1
Finished: step1
Finished: step1
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
Number of tests executed: 3
Number of tests executed: 3
Number of tests executed: 3

为什么JUnitExecutionListener方法第二次测试被调用两次,第三次测试被调用三次?我们可以对此进行修复,以便每个方法只能调用一次吗?

注意:我使用的是junit-4.12

1 个答案:

答案 0 :(得分:1)

RunNotifier在所有孩子之间共享:org.junit.runners.ParentRunner#runChildren。它基本上意味着每次为一个跑步者调用方法“run”时,监听器就会被添加到已经存在的可能包含你的监听器的RunNotifier对象中。

我认为有两种方法可以解决这个问题:

  1. 制作您的侦听器单例对象或仅将其存储在静态字段中,然后在添加之前只检查它是否已在列表中。
  2. 调用方法运行后删除侦听器。像这样:

    super.run(notifier);
    notifier.removeListener(listener);
    
  3. 希望它有用。