我发现 JUnit 的正确使用(或至少是文档)非常令人困惑。这个问题既可以作为未来的参考,也可以作为一个真实的问题。
如果我理解正确的话,创建和运行 JUnit 测试有两种主要方法:
方法 A(JUnit 3 风格):创建一个扩展 TestCase 的类,并以单词 test
开始测试方法。在将类作为 JUnit 测试(在 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);
}
}
将两者混合似乎不是一个好主意,请参见例如 this stackoverflow question:
现在,我的问题:
首选方法是什么,或者您什么时候使用其中一种而不是另一种?方法 B 允许通过扩展 @Test 注释来测试异常,如 @Test(expected = ArithmeticException.class)。但是在使用方法 A 时如何测试异常?使用方法 A 时,您可以将多个测试类分组到一个测试套件中,如下所示: TestSuite suite = new TestSuite("All tests"); suite.addTestSuite(DummyTestA.class); suite.addTestSuite(DummyTestAbis.class);但这不能与方法 B 一起使用(因为每个测试类都应该是 TestCase 的子类)。对方法 B 进行分组测试的正确方法是什么?
编辑:我已将 JUnit 版本添加到这两种方法中
extends TestCase
,然后每个测试也用 @Test
注释只是为了混淆。 :)
区别很简单:
扩展 TestCase 是用 JUnit 3 编写单元测试的方式(当然 JUnit 4 仍然支持它)
使用@Test注解是JUnit 4引入的方式
通常您应该选择注释路径,除非需要与 JUnit 3(和/或早于 Java 5 的 Java 版本)兼容。新方式有几个优点:
@Test 注释更明确,更容易在工具中支持(例如,通过这种方式搜索所有测试很容易)
可以使用 @Before/@BeforeClass 和 @After/@AfterClass 注释多个方法,从而提供更大的灵活性
支持诸如 ExpectedException 之类的 @Rule 注释
支持@Ignored 注解
使用 @RunWith 支持替代测试运行器
要测试 JUnit 3 TestCase
中的预期异常,您必须明确文本。
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 注释几乎相同。
我偏爱 JUnit 4(注释方法),因为我发现它更灵活。
如果您想在 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 */
}
您的问题有一个未回答的部分,那就是“为方法 B 分组测试的正确方法是什么?”
官方的回答是你用@RunWith(Suite.class) 注释一个类,然后使用@Suite.SuiteClasses 注释列出这些类。这就是 JUnit 开发人员的做法(手动列出套件中的每个类)。在许多方面,这种方法是一种改进,因为在套件之前和之后添加行为是微不足道和直观的(只需将 @BeforeClass 和 @AfterClass 方法添加到使用 @RunWith 注释的类 - 比旧的 TestFixture )。
但是,它确实倒退了一步,因为注释不允许您动态创建类列表,并且解决该问题有点难看。您必须对 Suite 类进行子类化并在子类中动态创建类数组并将其传递给 Suite 构造函数,但这是一个不完整的解决方案,因为 Suite 的其他子类(例如 Categories)不能使用它,而且本质上不支持动态测试类集合。
您应该使用 JUnit 4。它更好。
许多框架已经开始弃用 JUnit 3.8 支持。
这是来自 Spring 3.0 参考文档:
[警告] 不推荐使用旧版 JUnit 3.8 类层次结构
通常,当您开始新事物时,您应该始终尝试使用框架的最新稳定版本。
“首选”方法是使用自 Junit 4 以来引入的注释。它们使很多事情变得更容易(请参阅您的第二个问题)您可以为此使用简单的 try/catch 块:
public void testForException() {
try {
Integer.parseInt("just a string");
fail("Exception should have been thrown");
} catch (final Exception e) {
// expected
}
}
assertTrue(e.getMessage().contains("foo"))
可能会很有用。expected
方法仅检查类型。