问题
我应该在这样的声明中初始化类字段吗?
public class SomeTest extends TestCase
{
private final List list = new ArrayList();
public void testPopulateList()
{
// Add stuff to the list
// Assert the list contains what I expect
}
}
或者像setUp()这样?
public class SomeTest extends TestCase
{
private List list;
@Override
protected void setUp() throws Exception
{
super.setUp();
this.list = new ArrayList();
}
public void testPopulateList()
{
// Add stuff to the list
// Assert the list contains what I expect
}
}
我倾向于使用第一种形式,因为它更简洁,并允许我使用最终字段。如果我不需要使用setUp()方法进行设置,我还应该使用它,为什么?
**澄清:**JUnit将根据每种测试方法实例化一次测试类。这意味着每次测试都会创建list
,无论我在哪里声明它。这也意味着测试之间没有时间依赖关系。因此,使用setUp()似乎没有任何优势。但是JUnit FAQ有很多例子可以在setUp()中初始化一个空集合,所以我认为必须有一个原因。
#1 热门回答(86 赞)
如果你特别想知道JUnit常见问题解答中的例子,例如basic test template,我认为最好的做法是在测试中的类应该在你的setUp方法(或测试方法)中实例化。
当JUnit示例在setUp方法中创建一个ArrayList时,它们都会继续测试该ArrayList的行为,例如testIndexOutOfBoundException,testEmptyCollection等。有人写一个班级并确保它正常运作。
在测试自己的类时,你可能应该这样做:在setUp或测试方法中创建对象,这样如果以后打破它,你将能够获得合理的输出。
另一方面,如果你在测试代码中使用Java集合类(或其他类库),那可能不是因为你想要测试它 - 它只是测试夹具的一部分。在这种情况下,你可以安全地假设它按预期工作,因此在声明中初始化它不会有问题。
为了它的价值,我在一个相当大,几年,TDD开发的代码库上工作。我们习惯性地在测试代码的声明中初始化事物,并且在我参与这个项目的一年半中,它从未引起过任何问题。所以至少有一些轶事证据表明它是合理的。
#2 热门回答(41 赞)
我开始挖掘自己,我找到了使用setUp()
的一个潜在优势。如果在执行setUp()
期间抛出任何异常,JUnit将打印一个非常有用的堆栈跟踪。另一方面,如果在对象构造期间抛出异常,则错误消息只是说JUnit无法实例化测试用例,并且你没有看到发生故障的行号,可能是因为JUnit使用反射来实例化测试类。
这些都不适用于创建空集合的示例,因为它永远不会抛出,但它是setUp()
方法的优势。
#3 热门回答(17 赞)
除了Alex B的回答。
甚至需要使用setUp方法来实例化某种状态的资源。在构造函数中执行此操作不仅是时间问题,而且由于JUnit运行测试的方式,每个测试状态将在运行一个后被擦除。
JUnit首先为每个测试方法创建testClass的实例,并在创建每个实例后开始运行测试。在运行测试方法之前,运行其设置方法,其中可以准备一些状态。
如果将在构造函数中创建数据库状态,则在运行每个测试之前,所有实例都会在彼此之后立即实例化db状态。从第二次测试开始,测试将以脏状态运行。
JUnits生命周期:
- 为每个测试方法创建不同的testclass实例
- 对每个testclass实例重复:call setup调用testmethod
在测试中使用两种测试方法进行一些记录:(number是哈希码)
- 创建新实例:5718203
- 创建新实例:5947506
- 设置:5718203
- TestOne:5718203
- 设置:5947506
- TestTwo:5947506