当前位置:  开发笔记 > 编程语言 > 正文

最佳实践:在setUp()或声明中初始化JUnit类字段?

如何解决《最佳实践:在setUp()或声明中初始化JUnit类字段?》经验,为你挑选了7个好方法。

我应该在这样的声明中初始化类字段吗?

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> Moss Collum..:

如果你特别想知道JUnit FAQ中的例子,比如基本的测试模板,我认为最好的做法是在你的setUp方法(或测试方法)中实例化测试中的.

当JUnit示例在setUp方法中创建一个ArrayList时,它们都会继续测试该ArrayList的行为,例如testIndexOutOfBoundException,testEmptyCollection等.有人写一个班级并确保它正常运作.

在测试自己的类时,您可能应该这样做:在setUp或测试方法中创建对象,这样如果稍后打破它,您将能够获得合理的输出.

另一方面,如果在测试代码中使用Java集合类(或其他类库),则可能不是因为您想要测试它 - 它只是测试夹具的一部分.在这种情况下,您可以安全地假设它按预期工作,因此在声明中初始化它不会是一个问题.

为了它的价值,我开发了一个相当大,几年,TDD开发的代码库.我们习惯性地在测试代码的声明中初始化事物,并且在我参与这个项目的一年半中,它从未引起过任何问题.所以至少有一些轶事证据表明它是合理的.



2> Craig P. Mot..:

我开始挖掘自己,我找到了使用的一个潜在优势setUp().如果在执行期间抛出任何异常setUp(),JUnit将打印一个非常有用的堆栈跟踪.另一方面,如果在对象构造期间抛出异常,则错误消息只是说JUnit无法实例化测试用例,并且您没有看到发生故障的行号,可能是因为JUnit使用反射来实例化测试类.

这些都不适用于创建空集合的示例,因为它永远不会抛出,但这是该setUp()方法的一个优点.



3> Jurgen Hanna..:

除了Alex B的回答.

甚至需要使用setUp方法来实例化某种状态的资源.在构造函数中这样做不仅是时机的问题,但由于方式的JUnit运行测试,每个测试的状态将运行一个后被删除.

JUnit首先为每个测试方法创建testClass的实例,并在创建每个实例后开始运行测试.在运行测试方法之前,运行其设置方法,其中可以准备一些状态.

如果将在构造函数中创建数据库状态,则在运行每个测试之前,所有实例都会在彼此之后立即实例化db状态.从第二次测试开始,测试将以脏状态运行.

JUnits生命周期:

    为每个测试方法创建不同的testclass实例

    对每个testclass实例重复:调用setup +调用testmethod

在测试中使用两种测试方法进行一些记录:(number是哈希码)

创建新实例:5718203

创建新实例:5947506

设置:5718203

TestOne:5718203

设置:5947506

TestTwo:5947506


正确,但偏离主题.数据库本质上是全局状态.这不是我面临的问题.我只关心正确独立测试的执行速度.

4> Nils von Bar..:

在JUnit 4中:

对于Class Under Test,在@Before方法中初始化以捕获故障.

对于其他类,请在声明中初始化...

......为了简洁,并标记字段final,正如问题中所述,

...除非复杂的初始化可能会失败,在这种情况下使用@Before,以捕获失败.

对于全局状态(尤其是慢速初始化,如数据库),请使用@BeforeClass,但要注意测试之间的依赖关系.

单个测试中使用的对象的初始化当然应该在测试方法本身中完成.

@Before方法或测试方法中初始化可以让您更好地报告故障.这对于实例化被测试类(您可能会破坏)特别有用,但对于调用外部系统也很有用,例如文件系统访问("找不到文件")或连接到数据库("拒绝连接").

这是可以接受有一个简单的标准,而应使用@Before(明确的错误,但详细)或声明总是初始化(简洁但给人混乱的错误),因为复杂的编码规则是难以遵循,这是不是一个大问题.

初始化setUp是JUnit 3的遗留物,其中所有测试实例都是急切初始化的,如果进行昂贵的初始化,会导致问题(速度,内存,资源耗尽).因此,最佳实践是进行昂贵的初始化setUp,这仅在执行测试时运行.这不再适用,因此使用起来要少得多setUp.

这总结了其他几个埋葬lede的回复,特别是Craig P. Motlin(问题本身和自我答案),Moss Collum(被测试的课程)和dsaff.



5> dsaff..:

在JUnit 3中,在运行任何测试之前,每个测试方法将运行一次字段初始值设定项.只要你的字段值在内存中很小,占用很少的设置时间,并且不影响全局状态,使用字段初始化器在技术上是很好的.但是,如果这些不成立,您可能最终会在第一次测试运行之前消耗大量内存或设置字段,甚至可能耗尽内存.出于这个原因,许多开发人员总是在setUp()方法中设置字段值,即使它不是绝对必要的,它始终是安全的.

请注意,在JUnit 4中,测试对象初始化恰好在测试运行之前发生,因此使用字段初始值设定项更安全,并且建议使用样式.



6> amit..:

在你的情况下(创建一个列表),在实践中没有区别.但通常最好使用setUp(),因为这将有助于Junit正确报告异常.如果测试的构造函数/初始化程序中发生异常,则表示测试失败.但是,如果在安装过程中发生异常,很自然会将其视为设置测试时的一些问题,并且junit会对其进行适当的报告.



7> Alex B..:

我更喜欢可读性,最常见的是不使用设置方法.当基本设置操作需要很长时间并在每次测试中重复时,我会例外.
此时,我使用@BeforeClass注释将该功能移动到设置方法中(稍后进行优化).

使用@BeforeClasssetup方法进行优化的示例:我使用dbunit进行一些数据库功能测试.设置方法负责将数据库置于已知状态(非常慢...... 30秒 - 2分钟,具体取决于数据量).我在注释的setup方法中加载这些数据,@BeforeClass然后针对同一组数据运行10-20次测试,而不是在每次测试中重新加载/初始化数据库.

使用Junit 3.8(扩展TestCase,如示例所示)需要编写更多代码,而不仅仅是添加注释,但仍然可以"在类设置之前运行一次".

推荐阅读
coco2冰冰
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有