JUnit 混淆: 使用“扩展 TestCase”还是“@Test”?

我发现 JUnit 的正确使用(或者至少是文档)非常令人困惑。 这个问题既可以作为将来的参考,也可以作为一个真正的问题。

如果我理解正确的话,创建和运行 JUnit 测试有两种主要方法:

方法 A (JUnit 3-style) : 创建一个扩展 TestCase 的类,并用单词 test启动测试方法。当将该类作为 JUnit Test (在 Eclipse 中)运行时,将自动运行以单词 test开头的所有方法。

import junit.framework.TestCase;


public class DummyTestA extends TestCase {


public void testSum() {
int a = 5;
int b = 10;
int result = a + b;
assertEquals(15, result);
}
}

方法 B (JUnit 4风格) : 创建一个“普通”类,并在方法前面添加一个 @Test注释。请注意,您不必以单词 test开始该方法。

import org.junit.*;
import static org.junit.Assert.*;


public class DummyTestB {


@Test
public void Sum() {
int a = 5;
int b = 10;
int result = a + b;
assertEquals(15, result);
}
}

把两者混在一起似乎不是一个好主意,参见 这个堆栈溢出的问题:

现在,我的问题是:

  1. 什么是首选的方法 ,或者什么时候使用其中一种而不是另一种?
  2. 方法 B 允许通过像 @Test(expected = ArithmeticException.class).但是在使用方法 A 时如何测试异常?那样扩展@Test 注释来测试异常
  3. 当使用方法 A 时,您可以像下面这样在一个测试套件中分组许多测试类:

    TestSuite suite = new TestSuite("All tests");
    suite.addTestSuite(DummyTestA.class);
    suite.addTestSuite(DummyTestAbis.class); < br/> < br/> 但是这不能用于方法 B (因为每个测试类都应该是 TestCase 的子类)

编辑: 我已经将 JUnit 版本添加到这两种方法中

84559 次浏览

我更喜欢 JUnit4(注释方法) ,因为我发现它更加灵活。

如果您想要在 JUnit 4中构建测试套件,您必须创建一个类,像下面这样对所有测试进行分组:

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;




@RunWith(Suite.class)
@SuiteClasses({
Test1.class,
Test2.class,
Test3.class,
Test4.class
})public class TestSuite
{
/* empty class */
}

区别很简单:

  • 扩展 TestCase是在 JUnit3中编写单元测试的方式(当然,在 JUnit4中仍然支持)
  • 使用 @Test注释是 JUnit 4引入的方式

一般来说,您应该选择注释路径,除非需要与 JUnit3(和/或比 Java5更早的 Java 版本)兼容。这种新方法有几个优点:

要测试 JUnit3TestCase中的预期异常,您必须使文本显式化。

public void testMyException() {
try {
objectUnderTest.myMethod(EVIL_ARGUMENT);
fail("myMethod did not throw an Exception!");
} catch (MyException e) {
// ok!
// check for properties of exception here, if desired
}
}

JUnit 5 引入了另一个 API 更改,但仍然使用注释。新的 @Test注释是 org.junit.jupiter.api.Test(“旧的”JUnit 4注释是 org.junit.Test) ,但它的工作原理与 JUnit 4注释几乎相同。

  1. “首选”方法是使用自 Junit4以来引入的注释。它们让很多事情变得容易(见你的第二个问题)

  2. 您可以使用一个简单的 try/catch 块:


public void testForException() {
try {
Integer.parseInt("just a string");
fail("Exception should have been thrown");
} catch (final Exception e) {
// expected
}
}

你应该用 JUnit 4,它更好。

许多框架已经开始反对支持 JUnit 3.8。

这来自 Spring 3.0的参考文档:

[警告]遗产 JUnit 3.8类 不推荐使用层次结构

一般来说,当您开始一些新的东西时,您应该总是尝试使用一个框架的最新稳定版本。

你的问题有一部分没有得到回答,那就是“对方法 B 进行分组测试的正确方法是什么?”

官方的回答是,您使用@RunWith (Suite.class)注释一个类,然后使用@Suite。用于列出类的 SuiteClass 注释。JUnit 开发人员就是这样做的(手动列出套件中的每个类)。在许多方面,这种方法是一种改进,因为在套件之前和之后添加行为是琐碎和直观的(只需在用@RunWith 注释的类中添加一个@BeforeClass 和@AfterClass 方法——比旧的 TestFixture 要好得多)。

然而,它确实有一个倒退,因为注释不允许动态创建类列表,而解决这个问题就有点难看了。您必须对 Suite 类进行子类化,并在子类中动态创建类的数组,然后将其传递给 Suite 构造函数,但是这是一个不完整的解决方案,因为 Suite 的其他子类(比如类别)不能使用它,并且基本上不支持动态 Test 类集合。