Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为查询数据库的方法编写单元测试_C#_.net_Unit Testing_Nunit - Fatal编程技术网

C# 为查询数据库的方法编写单元测试

C# 为查询数据库的方法编写单元测试,c#,.net,unit-testing,nunit,C#,.net,Unit Testing,Nunit,我正在学习TDD,目前我有一个有效的方法,但我想我会尝试用TDD重建它 该方法基本上接受6个参数,查询数据库,执行一些逻辑并返回一个列表 我最初的测试包括检查空/零定义的字符串和int方法参数值,但现在我不确定该怎么做。如果我没有使用TDD,我只需要创建代码来查找DB连接字符串,打开DB连接,查询数据库,读取值等等 显然,在单元测试中我们不能做到这一点,所以我需要一些关于如何继续的建议。一般来说,使用TDD测试数据库代码并没有什么“错误”。但是,您可以尝试抽象出数据库代码,然后模拟出来。您可能希

我正在学习TDD,目前我有一个有效的方法,但我想我会尝试用TDD重建它

该方法基本上接受6个参数,查询数据库,执行一些逻辑并返回一个
列表

我最初的测试包括检查空/零定义的字符串和int方法参数值,但现在我不确定该怎么做。如果我没有使用TDD,我只需要创建代码来查找DB连接字符串,打开DB连接,查询数据库,读取值等等


显然,在单元测试中我们不能做到这一点,所以我需要一些关于如何继续的建议。

一般来说,使用TDD测试数据库代码并没有什么“错误”。但是,您可以尝试抽象出数据库代码,然后模拟出来。

您可能希望在数据访问层上运行单元测试。它使您的数据库在测试运行之间处于已知状态,防止测试数据库损坏。

请记住,TDD与良好的设计比与测试相关的内容更多。这种方法太多了;它违反了关注点分离原则

您已经确定了几个需要测试的领域:

该方法基本上接受6个参数,查询数据库,执行一些逻辑并返回一个
列表

这里有几个离散的步骤,代码中可能还有一些隐藏的步骤。当涉及到TDD时,打破这些是游戏的名称

首先,考虑执行逻辑的片段可能是一个好主意

您的方法是否动态构建查询?将该部分也分解出来,并对其进行测试,以确保查询编写正确

您可以将查询的执行放入一个独立的存储库或类似的存储库中,并针对该存储库编写集成测试。这样,您只需要对数据库进行一个简单的测试,而不是当前复杂的方法

如果您尝试按原样进行测试,您很可能会遇到一个需要大量设置并复制所有业务逻辑的怪物测试,当它崩溃时,您将不清楚到底出了什么问题

您可以:

  • 使用class/test init使用已知的数据集生成一个空白DB或一个小DB的副本
  • 在测试方法中输入测试数据(如果数据库为空),然后执行查询,然后将结果与预期结果进行比较
  • 在测试/类清理中,删除DB
  • 这将测试您的单元,但有些人认为这是“集成测试”。 -由于术语“单元”的模糊性,“单元测试”一词存在一些分歧

    您还可以使用内存中的DB或进程中的DB来简化测试环境

    该方法基本上接受6个参数,查询数据库,并执行以下操作 使用一些逻辑并返回一个列表

    这似乎太多了,不能成为一个单元可测试代码

    单元可测试代码应该做非常具体的事情,并在小模块中完成。因此,在您的情况下,您需要重构并将您的方法分解为(至少):

    • 数据库查询:包装在带有支持接口的数据提供程序中。您的单元测试将模拟这个接口
    • 做一些逻辑:这是单元测试的最佳候选者。这应该是一个模块,它只接受数据提供程序接口,执行逻辑并返回修改后的列表,您将在单元测试中验证该列表
    此外,请记住,单元测试应至少涵盖每个可测试模块的三种场景:

    • 阳性试验
    • 阴性试验
    • 测试为无效值引发有意义的异常

    希望这有帮助。

    另一种选择是在测试之前启动事务,然后执行回滚。这样,测试是独立的,所以根据一些定义,仍然可以被视为单元测试


    与其他答案中提到的相反,您应该重构代码,以便在测试通过后获得更好的设计。然后,您可以通过重新运行测试来验证重构没有破坏任何东西。

    Nitpick-如果它查询数据库,这是一个集成测试,而不是单元测试。@Oded:这是一个意见和争议的问题。@Oded-我在工作中多次说过这句话,这是不真实的@JohnsUnders-我想这取决于如何定义单元以及单元测试的约束应该是什么(速度、进程中等等)。有没有与.NET等效的?这个问题是.NET特有的。@DannyVarod通过谷歌快速搜索找到了这个项目:不错,但DAL技术特有。将演示数据库文件保存在源代码管理中,然后进行复制和附加将更加灵活。模拟它以返回查询中的数据片段?是的,非常灵活。为特定的测试返回特定的数据。所以我会说我应该有一个模拟存储库,它只返回一个内存中的数据列表,模拟数据库调用的数据列表?没错。你的逻辑可以据此发挥作用。这使您在测试正在进行的排序/过滤/处理时不再依赖数据库。它还可以防止将来数据库中出现导致测试“失败”的坏数据我是基于从DB/MockDB返回信息的新方法编写测试,还是基于现有方法编写测试,以确保调用返回DB信息的新方法时返回某些内容?我不确定我是否完全理解这个问题,但通常使用repository模式,您会完全创建一个新类,例如
    CustomerRepository
    。然后您可以创建方法,例如
    GetById
    GetAll
    。您可以测试,给定一个有效的客户ID,存储库返回一个具有该ID的客户,或者返回一个包含多个客户的列表。您的逻辑将作用于
    列表
    ,而不关心该
    列表
    来自何处。