当前位置: 首页 > 面试题库 >

如何在测试套件中定义JUnit方法规则?

艾晋
2023-03-14
问题内容

我有一个类,它是JUnit测试类的JUnit套件。我想定义规则 的上 套件 之前,并运行每个单元测试后做一些数据库 ,如果
某个注释存在对测试方法。

我已经能够@ClassRule在套件和测试类中创建一个将在每个
之前执行此操作(这不够好),并且我已经能够使用测试类本身来定义测试规则,但这是重复性的而且看起来不是很干。

是否可以在套件中定义每个测试方法的规则,还是必须将它们添加到每个测试中?

编辑: 为澄清起见,我想在套件中声明代码,该套件将在测试类中的测试方法之间(即“大约”)运行。


问题答案:

可以做到,但是需要一些工作。您需要定义自己的Suite运行程序和测试运行程序,然后在测试运行程序中覆盖runChild()。使用以下内容:

AllTests.java:

@RunWith(MySuite.class)
@SuiteClasses({Class1Test.class})
public class AllTests {
}

Class1Test.java:

public class Class1Test {
    @Deprecated @Test public void test1() {
        System.out.println("" + this.getClass().getName() + " test1");
    }

    @Test public void test2() {
        System.out.println("" + this.getClass().getName() + " test2");
    }
}

请注意,我注释test1()@Deprecated。当您@Deprecated在测试中具有注释时,您想做一些不同的事情,因此我们需要扩展Suite以使用自定义Runner

public class MySuite extends Suite {
    // copied from Suite
    private static Class<?>[] getAnnotatedClasses(Class<?> klass) throws InitializationError {
        Suite.SuiteClasses annotation = klass.getAnnotation(Suite.SuiteClasses.class);
        if (annotation == null) {
            throw new InitializationError(String.format("class '%s' must have a SuiteClasses annotation", klass.getName()));
        }
        return annotation.value();
    }

    // copied from Suite
    public MySuite(Class<?> klass, RunnerBuilder builder) throws InitializationError {
        super(null, getRunners(getAnnotatedClasses(klass)));
    }

    public static List<Runner> getRunners(Class<?>[] classes) throws InitializationError {
        List<Runner> runners = new LinkedList<Runner>();

        for (Class<?> klazz : classes) {
            runners.add(new MyRunner(klazz));
        }

        return runners;
    }
}

JUnit
Runner为将运行的每个测试创建一个。通常,Suite只会创建默认值BlockJUnit4ClassRunner,我们在这里所做的就是重写Suite的构造函数,该构造函数从SuiteClass批注中读取类,然后使用它们创建自己的运行程序MyRunner。这是我们的MyRunner类:

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

    @Override
    protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
        Description description= describeChild(method);
        if (method.getAnnotation(Ignore.class) != null) {
            notifier.fireTestIgnored(description);
        } else {
            if (description.getAnnotation(Deprecated.class) != null) {
                System.out.println("name=" + description.getMethodName() + " annotations=" + description.getAnnotations());
            }
            runLeaf(methodBlock(method), description, notifier);
        }
    }
}

大部分是从复制BlockJUnit4ClassRunner。我添加的位是:

if (description.getAnnotation(Deprecated.class) != null) {
    System.out.println("name=" + description.getMethodName() + " annotations=" + description.getAnnotations());
}

在这里我们测试@Deprecated方法上注释的存在,如果存在,请执行一些操作。剩下的作为练习留给读者。当我运行上面的套件时,我得到的输出是:

name=test1 annotations=[@java.lang.Deprecated(), @org.junit.Test(expected=class org.junit.Test$None, timeout=0)]
uk.co.farwell.junit.run.Class1Test test1
uk.co.farwell.junit.run.Class1Test test2

请注意,Suite具有多个构造函数,具体取决于调用方式。以上内容适用于Eclipse,但我尚未测试运行套件的其他方式。有关更多信息,请参见Suite的各种构造函数旁边的注释。



 类似资料:
  • 问题内容: 如何使用JUnit 4创建测试套件? 我看过的所有文档似乎都不适合我。而且,如果我使用Eclipse向导,它不会为我提供选择已创建的任何测试类的选项。 问题答案:

  • 问题内容: 我想使用JUnit 4创建一个junit测试套件,在运行测试套件之前,要包含的测试类的名称是未知的。 在JUnit 3中,我可以这样做: 并让该方法确定要运行的测试类。 在JUnit 4中,文档说要使用批注:构建我的测试套件。有许多SO答案显示了如何执行此操作。不幸的是,我看到的示例似乎不允许传递动态生成的TestClasses列表。 这样的建议我必须继承我不想做的子类。 动态指定的测

  • 我正在学习JUnit测试。我想在JUnit中测试getter和setter,但它不起作用。这是第一节课。 我需要如何更改以测试setter?我如何测试它?

  • 问题内容: 我有一个测试套件,其结构如下 在以上结构中,我想执行testmethod4()作为最后一个。即)最后执行。有一个@FixMethodOrder注释,它按顺序执行方法而不是testclass。是否有任何机制可以同时维护测试类和测试方法中的顺序。使用@FixMethodOrder,我可以通过重命名测试方法的名称来执行该方法,但是我不能指示junit将测试类作为最后一个(最后一个)执行。 问

  • 这是我当前的maven-surefire-plugin配置: