3

在某些情况下,单元测试可能非常困难。通常人们会说只测试你的公共 API。但在某些情况下,这是不可能的。如果您的公共 API 依赖于文件或数据库,则您无法正确进行单元测试。所以你会怎么做?

因为这是我第一次进行 TDD,所以我试图为单元测试找到“我的风格”,因为似乎没有唯一的方法可以做到这一点。我发现了两种解决这个问题的方法,它们一点都不完美。一方面,您可以尝试将您的程序集加为好友并测试内部功能。另一方面,您可以实现接口(仅出于单元测试的目的)并在单元测试中创建假对象。这种方法一开始看起来很不错,但当您尝试使用这些伪造品传输数据时变得更加丑陋。

这个问题有什么“好的”解决方案吗?其中哪个缺陷较少?还是有第三种方法?

4

3 回答 3

3

我在 TDD 中做了几个错误的开始,努力解决这个完全相同的问题。对我来说,当我意识到我的导师所说的“我们不想测试框架”的意思时,我的突破就来了。(在我们的例子中是 .Net 框架)。

在您的情况下,听起来好像您有一些与文件和数据库接口的业务逻辑。我要做的是在最薄的层中抽象文件和数据库逻辑。然后,您可以使用 Mock(假货或存根)来模拟文件和数据库层。这将允许您测试 if-my-database-returns-this-kind-of-information-does-my-business-logic-handle-it-correctly 之类的场景?同样对于文件访问,您可以测试确定要在哪个路径中打开哪个文件的代码,并且您可以测试您的逻辑是否能够正确分离任何给定文件的内容并能够正确使用它。

例如,如果您的文件访问层由一个函数组成,该函数采用路径名和文件名并以长字符串形式返回文件内容,那么您实际上不需要测试它,因为实际上您只是在进行一次调用到框架/操作系统,那里没有太多可能出错的地方。

目前,我正在开发一个系统,该系统将我们的数据库包装为一组返回 POCO 列表的函数。业务层易于理解,易于通过模拟进行模拟。

以这种方式工作需要一些时间来适应,但一旦它在你的脑海中点击,它就绝对是完美的。

最后,根据您的问题,我猜您正在使用遗留代码并尝试为新组件执行 TDD。这比在全新开发中进行 TDD 困难得多。如果可能,请尝试在新的(或隔离良好的)系统上进行第一次 TDD 尝试。一旦您了解了这些机制,将部分 TDD 的位引入遗留系统会容易得多。

于 2013-10-31T16:29:41.750 回答
2
If your public API depends on files or databases you can't unit test properly. So what do you do?

有一个可以使用的抽象级别。

  • IFileSystem/ IFileStorage(用于文件)
  • IRepository/ IDataStorage(用于数据库)

由于这个级别非常薄,它的集成测试将很容易编写和维护。所有其他代码都将是单元测试友好的,因为它很容易模拟与文件系统和数据库的交互。

On the one hand, you could try to friend your assemblies and test the features that are internal. 

当他们的类违反单一职责原则 (SRP)并且不使用依赖注入 (DI)时,人们会面临这个问题。

有一个很好的规则,即类只能通过其公共方法/属性进行测试。如果其他人使用内部方法,那么测试它们是可以接受的。由于测试,不应将私有或受保护的方法设置为内部方法。

On the other hand, you could implement interfaces (only for the purpose of unit testing) and create fake objects within your unit tests.  

是的,由于模拟框架的限制,接口很容易模拟。如果您可以创建一个类型的实例(假/存根),那么您的依赖项不应实现接口。

有时人们为他们的域实体使用接口,但我不支持它们。

为了简化处理假货的工作,使用了两种模式:

  1. 对象母亲
  2. 测试数据生成器

当我开始编写单元测试时,我从“Object Mother”开始。现在我正在使用“测试数据生成器”。

在Michael Feathers的《有效地使用遗留代码》一书中有很多好主意可以帮助你。

于 2013-11-01T13:24:25.653 回答
1

不要让困难的事情妨碍您...如果由于数据库或文件集成而固有地难以测试,请暂时忽略它。很可能你可以使用依赖注入等模拟将难以测试的东西重构为更容易测试的东西......在此之前,测试简单的东西并建立一个好的单元测试套件......当你进行重构时很难测试的东西,你将有一个更高的置信区间,它不会破坏其他任何东西......并且重构以使某些东西更容易测试是重构的一个很好的理由......

于 2013-10-31T22:14:52.843 回答