2011-07-16 37 views
26

我在JUnit中有很多测试用例。它们都需要使用相同的代码才能在其@BeforeClass静态方法中执行。这是一个代码重复,我试图摆脱它。这样做的一个肮脏的方式是继承。 JUnit中是否有其他机制,可能有所帮助?如何避免JUnit测试用例中的继承?

PS。我写了这篇关于这个主题的博客文章:http://www.yegor256.com/2015/05/25/unit-test-scaffolding.html

+0

所有'@ BeforeClasses'完全相同还是只是共享一些代码? –

+1

为什么继承是一种肮脏的方式? –

+0

@lu,该方法是静态的,继承不会是最好的。 –

回答

26

JUnit组成可重用代码(而不是从中继承)的方式是规则。

https://github.com/junit-team/junit/wiki/Rules

这是一个愚蠢的样品,但你会得到点。

import org.junit.rules.TestRule; 
import org.junit.runners.model.Statement; 
import org.junit.runner.Description; 

public class MyTestRule implements TestRule { 
    @Override 
    public Statement apply(final Statement statement, Description description) { 
    return new Statement() { 
     public void evaluate() throws Throwable { 
     // Here is BEFORE_CODE 
     try { 
      statement.evaluate(); 
     } finally { 
      // Here is AFTER_CODE 
     } 
     } 
    }; 
    } 
} 

然后,您可以使用您的TestRule这样的:

import org.junit.Rule; 

public class MyTest { 
    @Rule 
    public MyTestRule myRule = new MyTestRule(); 
} 

BEFORE_CODE和AFTER_CODE然后将围绕每个测试方法执行。

如果你需要为每个班级只运行一次你的代码,用你的TestRule作为@ClassRule:

import org.junit.ClassRule; 

public class MyTest { 
    @ClassRule 
    public static MyTestRule myRule = new MyTestRule(); 
} 

现在,BEFORE_CODEAFTER_CODE将围绕每个测试类的执行。

@Rule字段不是静态的,@ClassRule字段是。

@ClassRule也可以在套件中声明。

请注意,您可以在单个测试类中声明多个规则,这就是如何在测试套件,测试类和测试方法级别组成测试生命周期的方式。

规则是你在你的测试类中实例化的对象(静态或不静态)。如果需要,你可以添加构造器参数。

HTH

4

如果方法是某种实用工具,那么使用静态方法将其分离出来,并在@BeforeClass中调用该方法。

我强调这样一个事实,即不要仅仅因为它解决了你的问题而使用继承,而是在你的类层次结构中使用它。

0

如果每个类都需要有一个@BeforeClass标注的方法是正是一样每隔,然后继承不觉得我错了。如果这些初始化方法中的每一个都简单地共享代码,则可以使用某种共享行为创建一个TestUtil类,并调用每个@BeforeClass方法的此共享行为。

1

静态方法不会被继承,因此默认情况下继承不是一个选项。如果你的意思是你将方法移动到一个共同的父类,那么这看起来是一个糟糕的选择,因为你只能得到一个父Java。某种测试支持类似乎更合适。您也可能看到需要parameterized test

0

我认为如果这些类有“is-a”的关系,继承是合理的。

如果基类是MyBeforeClass定义@BeforeClass方法,和MyTestClass1“是一个” MyBeforeClassMyTestClass1 extends MyBeforeClass是OK。

0

根据设置代码的性质,您可以将所有测试放在测试suite中,并让设置代码在那里运行。缺点是你不能单独运行测试(因为测试取决于设置代码)。

1

在这种情况下,继承没有任何问题,它实际上是避免在每个子类中重复此代码的唯一方法。 @BeforeClass方法必须在JUnit中声明为静态的事实是不幸的,但这不应该阻止你。扩展该类,并且您可以自动运行初始化代码,而无需执行任何操作。

+0

不,它不是唯一的方法,看到其他答案,并且由于静态方法不被继承,它是否是一种方式是可疑的。你试过了吗? – EJP

2

您可以创建测试运行

public class MyTestRunner extends BlockJUnit4ClassRunner { 
    @Override 
    protected Object createTest() throws Exception { 
    Object test = super.createTest(); 
    doStuff(); 
    } 

    public void doStuff(){ 
    //common code 
    } 
} 


@RunWith(MyTestRunner.class) 
public class MyTest1{ 
    @Test 
    public void test1(){ 
     //test method 
    } 
} 
-2

这是测试代码,这并不意味着对重型再利用。不要过度设计。不要应用你所知道的所有设计模式。对于测试代码,规则是不同的。