【发布时间】:2010-05-02 11:02:45
【问题描述】:
我有几个存储库类用于与不同类型的数据进行通信,派生自IRepository 接口。
在实现中,代码与数据源对话,无论是 XML 文件目录还是数据库,甚至只是缓存。是否可以对这些实现中的任何一个进行可靠的单元测试?我没有看到模拟实现工作,因为那时我只测试模拟代码而不是实际代码。
【问题讨论】:
标签: c# unit-testing tdd mstest testing-strategies
我有几个存储库类用于与不同类型的数据进行通信,派生自IRepository 接口。
在实现中,代码与数据源对话,无论是 XML 文件目录还是数据库,甚至只是缓存。是否可以对这些实现中的任何一个进行可靠的单元测试?我没有看到模拟实现工作,因为那时我只测试模拟代码而不是实际代码。
【问题讨论】:
标签: c# unit-testing tdd mstest testing-strategies
不,当您编写一个使用 IRepository 的类时,您会使用模拟。对于IRepository 的实现,您需要针对适当的数据源进行测试。对于数据库来说,这有点让人头疼——对于文件系统来说,稍微少一点。
在可能的情况下,如果您可以用流或读取器来表达您的实现,那么您的工作将变得更轻松:对实现的这些部分的测试可以针对内存中的数据源,或者来自测试程序集中资源的流.当然,您可能需要一些测试,这些测试会转到真实数据库或文件系统,但希望更少。
您是否将此类测试称为“单元”测试取决于您如何定义单元测试;我个人不太关心涉及的名称,但我确实关心进行测试。特别是对于数据库,这些可能会有些痛苦(特别是如果您希望能够并行运行测试) - 但根据我的经验,它们也可能非常有价值。
【讨论】:
我认为,如果您正在测试实际持久化或查询数据的代码,您可能实际上想要访问数据库。
这些是集成测试而不是单元测试。
您可以设置一个测试数据库,您可以在其中了解数据的状态,然后针对该数据库运行测试。您可能还想告诉测试它们与您的单元测试不同,并且不需要在每次签入时都运行(在 nUnit 中,您可以使用属性来装饰您的测试类,告诉它不要运行)
【讨论】:
一般而言,您不会单元测试任何仅用于与数据源对话的代码。您可能仍希望自动测试存储库,但根据定义,这样的测试将是集成测试。您可能不想将这些测试作为“第一次通过”构建的一部分运行,例如设置数据库并自行清理可能需要相当长的时间。
如果您的存储库有其他职责(例如实现工作单元模式),那么您可能需要单独对这些职责进行单元测试。
【讨论】:
在 IRepository 的实现中,您将使用第三方 API,该 API 将实际读取/写入数据库/文件/xml。您要做的是模拟这些 API,以确保您的代码以正确的顺序调用正确的 API。
因此,如果您从数据库中读取数据,您可以模拟 SqlConnection 和 SqlCommand 并确保在这些类上调用正确的方法。如果您正在写入流,则可以模拟流并确保将其刷新并处置(例如)。
【讨论】: