Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.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
Database MSTest单元测试和数据库访问,而不接触实际数据库_Database_Unit Testing_Mstest_Clone - Fatal编程技术网

Database MSTest单元测试和数据库访问,而不接触实际数据库

Database MSTest单元测试和数据库访问,而不接触实际数据库,database,unit-testing,mstest,clone,Database,Unit Testing,Mstest,Clone,在我的代码中,我与数据库(不是解决方案文件的一部分)交互。数据库由单独的DBA团队拥有,我们开发人员编写的代码只允许访问存储的过程。然而,我们拥有数据库的进程、表和列(它的定义)的完整视图。对于依赖于数据的代码,我目前编写的单元测试会屏蔽表中的数据(并在单元测试完成后删除/删除这些行),因此我可以运行单元测试来练习与DB交互的代码。执行此操作的所有代码都在测试文件中(特别是在ClassInitialize()和ClassCleanup()函数中)。然而,我的新同事给了我一些悲伤,他们称我的单元测

在我的代码中,我与数据库(不是解决方案文件的一部分)交互。数据库由单独的DBA团队拥有,我们开发人员编写的代码只允许访问存储的过程。然而,我们拥有数据库的进程、表和列(它的定义)的完整视图。对于依赖于数据的代码,我目前编写的单元测试会屏蔽表中的数据(并在单元测试完成后删除/删除这些行),因此我可以运行单元测试来练习与DB交互的代码。执行此操作的所有代码都在测试文件中(特别是在ClassInitialize()和ClassCleanup()函数中)。然而,我的新同事给了我一些悲伤,他们称我的单元测试风格是“破坏性的”,因为我读/写dev数据库,插入和删除行。在我们编写单元测试代码时,数据库设计通常是不稳定的,因此很多时候,在我们将QA部门释放到程序上之前,我们可以在存储的过程代码中发现问题(节省资源)。他们都告诉我有一种方法可以在运行MSTest单元测试时将数据库克隆到内存中,但是他们不知道如何做。我已经在网络上进行了研究,但找不到一种方法来做同事需要我做的事情


有人能肯定地告诉我,在我上面展示的环境中,这种情况是否会发生?如果是这样,你能给我指出正确的方向吗?

我会模拟数据库,而不是尝试与测试实例交互。这将使您的测试更快(因此您更有可能运行它们)。

如果您可以在业务逻辑代码和数据访问层之间创建一个“接缝”,您应该可以。使用接口来表示DAL向业务逻辑公开的契约,然后编写自己的伪对象集或使用rhino mocks等模拟工具


如果您编写的测试击中了该数据库,那么您将面临巨大的维护难题,因为在您声明时,数据库正在发生变化,而且这也使得维护能够访问该数据库的环境变得非常困难。您实际编写的是集成测试,它们仍然有效,但真正的单元测试不应该依赖于数据库、文件系统、,等等。

假设您不能按照其他人的建议去做,因为您实际上是在测试存储过程,按照您的预期去做,那么我认为您的同事所指的是使用内存中的数据库

当人们谈论内存中的数据库进行测试时,他们通常指的是SQLite。他们在测试开始时在内存中建立数据库,并在测试结束时将其销毁。不幸的是,SQLite不支持存储过程,所以这对您没有帮助

我建议您为存储过程编写特定的集成测试,并像当前一样插入/删除数据。请注意,如果将测试包装在事务中,然后回滚,则会更容易。如果有可用的存储过程,还可以使用VisualStudio中的数据库“单元测试”功能来测试存储过程


在剩下的代码中,按照@Ben的建议模拟DAL,并作为正常的单元测试来测试业务逻辑。但是,考虑到DAL是一个静态类的复杂性,您需要做一些工作来包装DAL,并开始在整个应用程序中使用包装类-有点像ASP.NET MVC处理HttpContext的方式。

您有可以用来创建数据库的SQL脚本吗?你应该有,而且他们应该在版本控制之下。如果是,则可以执行以下操作:

在测试设置代码中:

  • 使用SQL脚本创建“临时”数据库。使用一个唯一的名称,例如unitTestDatabase_U9;[时间戳]
  • 在测试数据库中设置测试所需的数据。理想情况下使用公共API函数(例如CreateUser、AddNewCustomer),但如果所需API不存在,则使用SQL命令。使用API设置测试数据可以使测试对底层实现(即数据库模式)的更改更加健壮。这就是我们编写单元测试的原因之一,以确保对实现的更改不会破坏功能
  • 运行单元测试,使用依赖项注入将测试数据库连接字符串从测试代码传递到被测试代码中
然后在测试拆卸代码中删除数据库。理想情况下,应该使用您的数据库卸载脚本完成,该脚本也应该处于版本控制之下

通过在[AssemblyInitialize]、[ClassInitialize]或[TestInitialize]方法中创建数据库,您可以控制创建单元测试数据库的频率:例如,每个测试项目、测试类或测试方法,或组合

这是一种我们非常成功地使用的技术。的优点是:

  • 每次运行单元测试时,我们都在测试数据库安装脚本是否与代码一起工作
  • 测试隔离,即测试只影响其测试数据库。如果回滚代码出错,也无所谓,因为您没有接触任何其他人的数据
  • 对代码的信心。也就是说,因为我们使用的是一个真实的数据库,所以与模拟数据库相比,单元测试让我对代码的工作更有信心。当然,这取决于您的高级集成/组件测试套件有多好
缺点

  • 单元测试依赖于外部系统(DBMS)。您需要在测试设置代码中找到DBMS的名称。这可以通过使用配置文件或查看正在运行的本地DBMS的运行时来完成
  • 数据库安装脚本可能会减慢测试速度。根据我们的经验,测试仍在快速运行