【问题标题】:How do you unit test a class that's meant to talk to data?您如何对旨在与数据对话的类进行单元测试?
【发布时间】:2010-05-02 11:02:45
【问题描述】:

我有几个存储库类用于与不同类型的数据进行通信,派生自IRepository 接口。

在实现中,代码与数据源对话,无论是 XML 文件目录还是数据库,甚至只是缓存。是否可以对这些实现中的任何一个进行可靠的单元测试?我没有看到模拟实现工作,因为那时我只测试模拟代码而不是实际代码。

【问题讨论】:

    标签: c# unit-testing tdd mstest testing-strategies


    【解决方案1】:

    不,当您编写一个使用 IRepository 的类时,您会使用模拟。对于IRepository实现,您需要针对适当的数据源进行测试。对于数据库来说,这有点让人头疼——对于文件系统来说,稍微少一点。

    在可能的情况下,如果您可以用流或读取器来表达您的实现,那么您的工作将变得更轻松:对实现的这些部分的测试可以针对内存中的数据源,或者来自测试程序集中资源的流.当然,您可能需要一些测试,这些测试会转到真实数据库或文件系统,但希望更少。

    您是否将此类测试称为“单元”测试取决于您如何定义单元测试;我个人不太关心涉及的名称,但我确实关心进行测试。特别是对于数据库,这些可能会有些痛苦(特别是如果您希望能够并行运行测试) - 但根据我的经验,它们也可能非常有价值。

    【讨论】:

      【解决方案2】:

      我认为,如果您正在测试实际持久化或查询数据的代码,您可能实际上想要访问数据库。

      这些是集成测试而不是单元测试。

      您可以设置一个测试数据库,您可以在其中了解数据的状态,然后针对该数据库运行测试。您可能还想告诉测试它们与您的单元测试不同,并且不需要在每次签入时都运行(在 nUnit 中,您可以使用属性来装饰您的测试类,告诉它不要运行)

      【讨论】:

        【解决方案3】:

        一般而言,您不会单元测试任何仅用于与数据源对话的代码。您可能仍希望自动测试存储库,但根据定义,这样的测试将是集成测试。您可能不想将这些测试作为“第一次通过”构建的一部分运行,例如设置数据库并自行清理可能需要相当长的时间。

        如果您的存储库有其他职责(例如实现工作单元模式),那么您可能需要单独对这些职责进行单元测试。

        【讨论】:

          【解决方案4】:

          在 IRepository 的实现中,您将使用第三方 API,该 API 将实际读取/写入数据库/文件/xml。您要做的是模拟这些 API,以确保您的代码以正确的顺序调用正确的 API。

          因此,如果您从数据库中读取数据,您可以模拟 SqlConnection 和 SqlCommand 并确保在这些类上调用正确的方法。如果您正在写入流,则可以模拟流并确保将其刷新并处置(例如)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-17
            • 1970-01-01
            • 1970-01-01
            • 2018-02-11
            • 2014-05-21
            • 2010-12-14
            • 1970-01-01
            相关资源
            最近更新 更多