tdd - 为第三方代码创建测试

时间:2015-02-16 14:21:24

标签: unit-testing testing tdd functional-testing functional-dependencies

如果我正在测试的方法或程序依赖于来自第三方的一段代码,我该如何创建单元测试?说,我有一个方法,它使用来自第三方源的类,这些类需要只能在功能测试中完成的设置。我该怎么做呢?大多数情况下,第三方依赖不能被嘲笑,但我的方法确实需要使用它。

另外,我应该通过利用实际数据来避免单元测试甚至功能测试吗?比如,我的测试是否永远不会连接到数据库API以临时添加数据,对其进行操作和测试,然后将其删除?

3 个答案:

答案 0 :(得分:6)

单元测试

你应该测试一切。但不是所有使用单元测试的东西。单元测试不依赖于环境 - 数据库,互联网连接等。使用不受信任/不稳定的第三方工具的最佳实践是在您的代码和第三方代码之间创建反腐败层。因此,重构您的代码,使您的业务逻辑尽可能独立。并对业务逻辑进行单元测试。

如果您不确定第三方代码的工作原理或将来是否会发生变化,您可以进行“学习测试”。这些是断言你依赖的行为的单元测试(如果可能的话)。在学习测试中,您只测试第三方代码,而不是您的代码

如果第三方代码不受信任(众所周知的开源库),那么你认为它可行,不做任何分离,你只对你的代码进行单元测试,而不是库。

非单元测试

如果您的测试需要外部环境(db,network等),那么您应该进行集成测试。它的目的不是测试业务逻辑,而是如果你正确连接所有部分。 SQL测试是最着名的例外之一。

没有简单的规则如何进行集成测试(你可以写关于sql测试的书籍)。这取决于您想要测试的内容,与您需要/想要的生产环境有多少相似之处。例如,您可以针对内存数据库或类似生产的数据库(oracle,postgres等)进行sql测试。但是,如果您设计集成测试,则必须确保每个测试都以知道环境状态开始。并且您已经考虑了将环境置于肮脏状态和此类测试速度的错误

答案 1 :(得分:6)

你说:

  

大多数情况下,第三方依赖不能被嘲笑

为什么呢?您始终可以为与第三方组件的交互定义接口,然后提供一个实现,只需将每个调用委托给第三方组件,然后您就可以为测试提供此接口的模拟。

如果第三方组件有一个大型API,这可能会有很多工作,但它仍然值得做。

类似的projects用于创建.net文件系统类的包装器,以便您可以编写不依赖于文件系统的测试。

所以你可以这样做:

public interface IMyDependency
{
    public void SomeMethod();

    public int CaclateSomething();

    //add other methods that you will call in the 3rd party dependency
}

然后有一个包装器,它只委托给你正在使用的实际第三方组件,如下所示:

public class MyDependencyWrapper : IMyDependency
{
    private My3rdPartyDepency actualDependency;

    public MyDependencyWrapper(My3rdPartyDepency actualDependency)
    {
         this.actualDependency=actualDependency;
    }

    public void SomeMethod()
    {
        actualDependency.SomeMethod()l
    }

    public int CaclateSomething(string aParam)
    {
        return actualDependency.CalculateSomething(aParam);
    }

    //add other methods that you will call in the 3rd party dependency
}

现在使用它可以只使用测试中的接口,因此可以编写单元测试而不依赖于实际的第三方组件。

答案 2 :(得分:3)

通常,假设第三方软件已经过测试并且工作正常。虽然当你发现一个bug时它会让你感到惊讶。

这取决于你的单元测试。有些事情,例如访问一些异国情调的硬件或资源,或简单的网络连接,不应该进行单元测试。对于这样的调用,我们使用模拟,不进行单元测试。

对于数据库,您可以使用模拟而不是真实类来访问数据库。或者,您可以在单元测试设置方法中在内存中创建数据库,并在清理中销毁它们。