C# 为查询数据库的方法编写单元测试
我正在学习TDD,目前我有一个有效的方法,但我想我会尝试用TDD重建它 该方法基本上接受6个参数,查询数据库,执行一些逻辑并返回一个C# 为查询数据库的方法编写单元测试,c#,.net,unit-testing,nunit,C#,.net,Unit Testing,Nunit,我正在学习TDD,目前我有一个有效的方法,但我想我会尝试用TDD重建它 该方法基本上接受6个参数,查询数据库,执行一些逻辑并返回一个列表 我最初的测试包括检查空/零定义的字符串和int方法参数值,但现在我不确定该怎么做。如果我没有使用TDD,我只需要创建代码来查找DB连接字符串,打开DB连接,查询数据库,读取值等等 显然,在单元测试中我们不能做到这一点,所以我需要一些关于如何继续的建议。一般来说,使用TDD测试数据库代码并没有什么“错误”。但是,您可以尝试抽象出数据库代码,然后模拟出来。您可能希
列表
我最初的测试包括检查空/零定义的字符串和int方法参数值,但现在我不确定该怎么做。如果我没有使用TDD,我只需要创建代码来查找DB连接字符串,打开DB连接,查询数据库,读取值等等
显然,在单元测试中我们不能做到这一点,所以我需要一些关于如何继续的建议。一般来说,使用TDD测试数据库代码并没有什么“错误”。但是,您可以尝试抽象出数据库代码,然后模拟出来。您可能希望在数据访问层上运行单元测试。它使您的数据库在测试运行之间处于已知状态,防止测试数据库损坏。请记住,TDD与良好的设计比与测试相关的内容更多。这种方法太多了;它违反了关注点分离原则 您已经确定了几个需要测试的领域: 该方法基本上接受6个参数,查询数据库,执行一些逻辑并返回一个
列表
这里有几个离散的步骤,代码中可能还有一些隐藏的步骤。当涉及到TDD时,打破这些是游戏的名称
首先,考虑执行逻辑的片段可能是一个好主意
您的方法是否动态构建查询?将该部分也分解出来,并对其进行测试,以确保查询编写正确
您可以将查询的执行放入一个独立的存储库或类似的存储库中,并针对该存储库编写集成测试。这样,您只需要对数据库进行一个简单的测试,而不是当前复杂的方法
如果您尝试按原样进行测试,您很可能会遇到一个需要大量设置并复制所有业务逻辑的怪物测试,当它崩溃时,您将不清楚到底出了什么问题 您可以:
- 数据库查询:包装在带有支持接口的数据提供程序中。您的单元测试将模拟这个接口
- 做一些逻辑:这是单元测试的最佳候选者。这应该是一个模块,它只接受数据提供程序接口,执行逻辑并返回修改后的列表,您将在单元测试中验证该列表
- 阳性试验
- 阴性试验
- 测试为无效值引发有意义的异常
希望这有帮助。另一种选择是在测试之前启动事务,然后执行回滚。这样,测试是独立的,所以根据一些定义,仍然可以被视为单元测试
与其他答案中提到的相反,您应该重构代码,以便在测试通过后获得更好的设计。然后,您可以通过重新运行测试来验证重构没有破坏任何东西。Nitpick-如果它查询数据库,这是一个集成测试,而不是单元测试。@Oded:这是一个意见和争议的问题。@Oded-我在工作中多次说过这句话,这是不真实的@JohnsUnders-我想这取决于如何定义单元以及单元测试的约束应该是什么(速度、进程中等等)。有没有与.NET等效的?这个问题是.NET特有的。@DannyVarod通过谷歌快速搜索找到了这个项目:不错,但DAL技术特有。将演示数据库文件保存在源代码管理中,然后进行复制和附加将更加灵活。模拟它以返回查询中的数据片段?是的,非常灵活。为特定的测试返回特定的数据。所以我会说我应该有一个模拟存储库,它只返回一个内存中的数据列表,模拟数据库调用的数据列表?没错。你的逻辑可以据此发挥作用。这使您在测试正在进行的排序/过滤/处理时不再依赖数据库。它还可以防止将来数据库中出现导致测试“失败”的坏数据我是基于从DB/MockDB返回信息的新方法编写测试,还是基于现有方法编写测试,以确保调用返回DB信息的新方法时返回某些内容?我不确定我是否完全理解这个问题,但通常使用repository模式,您会完全创建一个新类,例如
CustomerRepository
。然后您可以创建方法,例如GetById
和GetAll
。您可以测试,给定一个有效的客户ID,存储库返回一个具有该ID的客户,或者返回一个包含多个客户的列表。您的逻辑将作用于列表
,而不关心该列表
来自何处。