2012-08-23 46 views
74

我设置了一个测试类,而不是使用@Before我想要一个在所有测试前只执行一次的设置方法。 Junit 4.8有可能吗?Junit - 运行设置方法一次

+0

看看RunListener:http://stackoverflow.com/a/14773170/548473 – GKislin

回答

130

虽然我@assylias同意使用@BeforeClass是一个典型的解决方案并不总是方便。用@BeforeClass注释的方法必须是静态的。一些需要测试用例的测试非常不方便。例如,基于Spring的测试使用@Autowired来处理在spring上下文中定义的服务。

在这种情况下,我个人使用标注有@Before注释定期setUp()方法和管理我的自定义boolean标志:

private static boolean setUpIsDone = false; 
..... 
public void setUp() { 
    if (setUpIsDone) { 
     return; 
    } 
    // do the setup 
    setUpIsDone = true; 
} 
+15

setUpIsDone变量应该是静态的,以及您想要在setUp()中实例化的每个@Test方法中使用的其他对象。 –

+4

添加到肯尼卡森的评论为什么它必须是静态的。它必须是静态的,因为JUnit为每个@Test方法实例化一个新的测试类实例。如果它不是静态的,那么实例变量将被重置为默认值(假)。有关详细信息,请参阅:http://martinfowler.com/bliki/JunitNewInstance.html –

+2

这适用于除''setUp()'方法在超类中的情况 - 已发布[answer](http:// stackoverflow .com/questions/12087959#31117171)试图解决这个问题。 –

67

您可以使用the BeforeClass annotation

@BeforeClass 
public static void setUpClass() { 
    //executed only once, before the first test 
} 
+6

我不能使用这个,我有几个基于非静态组件的设置方法,如getClass() – Bober02

+1

@ Bober02 BeforeClass需要确实是静态的。如果你不能使用它,另一个答案提供了一种解决方法。 – assylias

+2

当然你不能使用'TheClassYouWant.class'而不是你的getClass()调用?这是实际的Java:'String.class.getName()'。 – stolsvik

4

setUp()是在实际测试的超类,公认的答案可以作如下修改:

public abstract class AbstractTestBase { 
    private static Class<? extends AbstractTestBase> testClass; 
    ..... 
    public void setUp() { 
     if (this.getClass().equals(testClass)) { 
      return; 
     } 

     // do the setup - once per concrete test class 
     ..... 
     testClass = this.getClass(); 
    } 
} 

这应该适用于一个单一的非静态设置()方法,但我不误入是无法生产的拆卸()等效一个复杂的反思世界......奖金指向任何人谁可以!

0

编辑: 我才发现这是在调试类是每次测试之前实例化了。 我猜@BeforeClass注解是最好的。

你也可以在构造函数上设置,测试类毕竟是一个类。 我不确定这是否是一种不好的做法,因为几乎所有其他方法都被注释了,但它起作用。你可以创建一个这样的构造:

public UT() { 
    // initialize once here 
} 
@Test 
// Some test here... 

的构造函数将在测试之前,因为它们不是静态的调用。

16

的JUnit 5现在有一个@BeforeAll注释:

表示该注释的方法应之前执行的所有@Test 方法在当前类或类层次;类似JUnit 4的@BeforeClass。这些方法必须是静态的。

JUnit 5的生命周期注释似乎终于得到它了!你能猜到这看也不看注解可用(例如@BeforeEach @AfterAll)

+1

'@ BeforeClass'有同样的问题,它需要是'static'。 IMO @ AlexR的解决方案更好。 – zengr

+0

@zengr倾向于同意你的观点:正如我对AlexR所说的,他的解决方案要求所有测试类都从CommonTest类继承,如果它只运行一次。但这很简单,恕我直言,恕我直言,你可能不应该使用一种“花哨”的框架提供的解决方案,当一种简单的机制可以从语言中获得。除非当然有充分的理由。此外,使用像他这样的简单的东西,用一个好的“做它所说的锡”类型名称,有助于提高可读性。 –

+0

话虽如此,恕我直言,似乎有更多的理由有一个“AfterAll”注释:这将是非常困难和设计一个机制来检测何时完成所有测试。相反,当然,纯粹主义者可能会说你不应该做“最后的清理”,即每个“tearDown”应该使所有资源保持原始状态......并且他们可能是对的! –

0

我肮脏的解决方案是:

public class TestCaseExtended extends TestCase { 

    private boolean isInitialized = false; 
    private int serId; 

    @Override 
    public void setUp() throws Exception { 
     super.setUp(); 
     if(!isInitialized) { 
      loadSaveNewSerId(); 
      emptyTestResultsDirectory(); 
      isInitialized = true; 
     } 
    } 

    ... 

} 

我用它作为基地基地,我所有的测试用例。

+0

public class TestCaseExtended extends TestCase private static boolean isInitialized = false; 私有静态TestCaseExtended caseExtended; private int serId; @Override public void setUp()throws Exception { super.setUp();如果(!isInitialized){ caseExtended = new TestCaseExtended(); caseExtended.loadSaveNewSerId(); caseExtended.emptyTestResultsDirectory(); isInitialized = true; } } –