单元测试遗留代码,不使用DI

本文关键字:DI 代码 单元测试 | 更新日期: 2023-09-27 18:16:24

我们正在尝试将单元测试添加到业务层中。技术栈是asp.net web forms, WCF, ADO。. Net调用存储过程)。业务层在数据类上调用静态方法,因此在不做大量更改的情况下引入DI是很困难的。

这可能不是一个传统的方式去做,但我正在考虑保持DB在单元测试(依赖),但使用它作为一个测试DB…要么使用现有的冻结数据库,要么在表中模拟数据。我想知道使用测试数据库的可行性,其中存储过程像mock一样使用。不需要复制整个数据库,只需创建由存储过程命名的表名。存储过程将只调用一个表,并返回静态数据……从本质上讲,尝试用类似Moq的东西来模拟mock数据的功能,但从DB的角度来看。

谁能推荐任何设计,将包括DB在测试中,仍然是确定性的?

单元测试遗留代码,不使用DI

如果您想在测试中使用DB,并且让所有内容都是确定的,那么您需要每个测试都有自己的DB,这意味着为每个测试创建(并可能填充)一个新的DB。

这取决于你的DB层如何创建它的连接。我通过在测试设置中使用localDb生成DB,并为名称指定GUID,然后在拆除测试结束时再次删除DB,从而完成了类似的操作。

它最终会相当慢(并不奇怪),但是在Ram磁盘驱动器上创建db有助于解决这个问题。

这对于空DB来说工作正常,然后有EF创建的模式,但是如果您需要DB中的固定数据集,那么您可能需要从测试

的设置中的备份中恢复它。

在我看来,在每次测试调用存储过程时,设置存储过程来执行您希望它们执行的操作将是一项大量的工作,并且您最终仍然会遇到数据库始终存在的速度问题。我建议您使用以下一种或两种方法:

  1. 使用TypeMock,它有一个强大的隔离工具。它基本上改变了你的编译,使单元测试甚至可以模拟静态方法。
  2. 尝试创建"验收测试",而不仅仅是单元测试,它侧重于模拟完整的用户体验:登录、创建对象、查看对象(验证对象看起来正确)、更新对象、再次查看对象(同上)、删除对象(验证对象已删除)。通过设置此特定测试所需的所有对象开始每个测试,并在结束时删除所有这些对象,以便其他测试可以基于假设的启动状态运行。

第一种方法为您提供了真正的"单元"测试的速度和可模拟性,而第二种方法允许您练习更多的代码,增加了捕获错误的可能性,甚至在存储过程中也是如此。