如何避免单元测试中不必要的前提条件?

时间:2014-08-19 13:44:13

标签: unit-testing

理想情况下,为生产代码中的每个类编写测试类。在测试类中,所有测试方法可能不需要相同的前提条件。我们如何解决这个问题? 我们是否为这些创建单独的测试类?

3 个答案:

答案 0 :(得分:1)

可以选择在同一个类中使用相同的前提条件对测试进行分组,这也有助于避免超过一千行的测试类。您还可以在单​​独的方法中创建前置条件,并让每个测试调用适用的方法。当大多数方法具有不同的前提条件时,您可以执行此操作,否则您可以使用在测试之前调用的安装方法。

答案 1 :(得分:1)

我建议创建包含必要的前提条件设置的单独方法。不要将此方法与传统的测试设置混淆。例如,假设您为收据提供程序编写了测试,搜索存储库并根据某些验证步骤返回收据。我们最终可能会:

  • 收据在存储库中不存在:return null
  • 收据存在,但与验证者日期不匹配:return null
  • 收据存在,匹配验证日期,但未完全提交(即未被某些外部系统处理):return null

我们在这里有几个条件:收据存在/不存在,收据在日期方式无效,收据未提交。我们的快乐路径是默认设置(例如通过传统的测试设置完成)。然后,快乐路径测试就像(一些C#伪代码)一样简单:

[Test]
public void GetReceipt_ReturnsReceipt()
{
    receiptProvider.GetReceipt("701").IsNotNull();
}

现在,对于特殊情况,我们只需编写微小的专用方法来安排我们的测试环境(例如设置依赖关系),以便满足条件:

[Test]
public void GetReceipt_ReturnsNull_WhenReceiptDoesntExist()
{
    ReceiptDoesNotExistInRepository("701")
    receiptProvider.GetReceipt("701").IsNull();
}

[Test]
public void GetReceipt_ReturnsNull_WhenExistingReceiptHasInvalidDate()
{
    ReceiptHasInvalidDate("701");
    receiptProvider.GetReceipt("701").IsNull();
}

您最终会得到一些额外的辅助方法,但您的测试将更容易阅读和理解。当逻辑比简单的yes-no设置更复杂时,这尤其有用:

[Test]
public void GetReceipt_ThrowsException_WhenUncommittedReceiptHasInvalidDate()
{
    ReceiptHasInvalidDate("701");
    ReceiptIsUncommitted("701");
    receiptProvider.GetReceipt("701").Throws<Exception>();
}

答案 2 :(得分:0)

我喜欢使用在每次测试运行之前调用的Setup方法。在这个方法中,我实例化了我想要测试的类,为它提供了需要创建的任何依赖项。然后我将在测试方法中设置各个测试的具体细节。它将类的任何常见初始化移至setup方法,并允许测试专注于需要评估的内容。

您可能会发现此链接很有价值,它讨论了测试设置的方法: In Defense of Test Setup Methods, by Erik Dietrich