集成测试:我做得对吗?

时间:2011-06-21 08:28:37

标签: c# nunit automated-tests integration-testing

这是我为与数据库交互的类编写的集成测试:

[Test]
public void SaveUser()
{
    // Arrange
    var user = new User();
    // Set a bunch of properties of the above User object

    // Act
    var usersCountPreSave = repository.SearchSubscribersByUsername(user.Username).Count();
    repository.Save(user);
    var usersCountPostSave = repository.SearchSubscribersByUsername(user.Username).Count();

    // Assert
    Assert.AreEqual(userCountPreSave + 1, userCountPostSave);
}

在我看来,我无法在不涉及Save函数的情况下测试SearchSubscriberByUsername函数,以确定用户是否已成功保存。我意识到集成测试并不是单元测试,它应该一次测试一个代码单元。但理想情况下,如果我可以在每次测试中测试我的存储库类中的一个函数,那将会很好,但我不知道如何实现它。

到目前为止我是如何编写代码还是有更好的方法?

4 个答案:

答案 0 :(得分:8)

您的测试有问题。当您测试将数据保存到数据库中时,您应该测试它是否在数据库中,而不是存储库说它在数据库中。

如果您正在测试存储库的功能,那么您无法通过询问它是否已正确完成来验证该功能。这相当于对某人说'你做得对吗?'他们会说是的。

想象一下,存储库永远不会提交。您的测试将正常通过,但数据将不在数据库中。

所以,我要做的是打开数据库的连接(纯SQL)并检查数据是否已正确保存。您只需要在之前和之后选择计数(*)以确保用户已被保存。如果这样做,您也可以避免使用SearchSubscribersByUsername。

如果您正在测试存储库的功能,则根据定义,您无法信任存储库。

答案 1 :(得分:2)

要对“保存”功能进行单元测试,您肯定需要一些值得信赖的通道来检查操作结果。如果您信任SearchSubscribersByUsername(因为您已经为该功能自行完成了一些单元测试),您可以在此处使用它。

如果您不信任SearchSubscribersByUsername,并且您认为您的单元测试也可能因为该函数中存在错误(而不是Save)而中断,则应考虑使用其他渠道(也许您有可能绕过对数据库的SQL访问来检查Save结果,这可能比SearchSubscribersByUsername的实现更简单?但是,不要再次重新实现SearchSubscribersByUsername,这将变得毫无意义。无论哪种方式,您至少需要一些其他可以信任的功能。

答案 2 :(得分:1)

除非您测试的方法返回有关您所做的事情的确切信息,否则我认为没有办法避免调用其他方法。我认为你认为集成测试需要一种不同的单元测试思维方式​​是正确的。

我仍然会构建专注于单个方法的测试。所以在测试Save()时我可能会使用Search()的功能,但我的重点是Save()的边缘情况。我构建了处理重复插入或无效输入数据的测试。然后我构建了一大堆Search()测试来处理Search()的边缘情况。

现在一种可能的思维方式是Save和Search有一些共性,Search中的错误可能会掩盖Save中的错误。想象一下,例如,如果你有一个缓存层。因此,另一种方法可能是使用其他一些验证机制。例如,对数据库的直接JDBC调用,或者在基础结构中的某个位置替代地引入模拟层。在构建复杂的集成系统时,这种“后门”验证可能是必不可少的。

答案 3 :(得分:0)

就个人而言,我已经写了无数与此非常相似的测试并认为它很好。另一种方法是将数据库存根,以便searchSubscribers永远不会做任何事情,但是我所说的很多工作都没什么用。