gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:52:21 24 4
gpt4 key购买 nike

我有一个类是 JUnit 测试类的 JUnit 套件。我想在 suite 上定义一个规则在每个单元测试运行之前和之后对数据库做一些事情如果某个注释是介绍该测试方法。

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

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

编辑:为了澄清,我想在一个套件中声明代码,该代码将在测试类中的测试方法之间(即“围绕”)运行。

最佳答案

这是可以做到的,但需要做一些工作。您还需要定义自己的套件运行器和测试运行器,然后覆盖测试运行器中的 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");
}
}

请注意,我已使用 @Deprecated 注释了 test1()。当您在测试中使用 @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 的各种构造函数旁边的注释。

关于java - 如何在测试套件中定义 JUnit 方法规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7639353/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com