Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.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
Oop 如何对非公共逻辑进行单元测试_Oop_Unit Testing_Tdd - Fatal编程技术网

Oop 如何对非公共逻辑进行单元测试

Oop 如何对非公共逻辑进行单元测试,oop,unit-testing,tdd,Oop,Unit Testing,Tdd,在某些情况下,单元测试可能非常困难。通常人们说只测试你的公共API。但在某些情况下,这是不可能的。如果您的公共API依赖于文件或数据库,则无法正确进行单元测试。那你是做什么的 因为这是我第一次使用TDD,所以我试图找到单元测试的“我的风格”,因为似乎没有一种方法可以做到这一点。我在这个问题上找到了两种方法,它们并非完美无缺。一方面,您可以尝试与程序集交朋友,并测试内部特性。另一方面,您可以实现接口(仅用于单元测试),并在单元测试中创建假对象。这种方法一开始看起来很不错,但当您试图使用这些赝品传输

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

因为这是我第一次使用TDD,所以我试图找到单元测试的“我的风格”,因为似乎没有一种方法可以做到这一点。我在这个问题上找到了两种方法,它们并非完美无缺。一方面,您可以尝试与程序集交朋友,并测试内部特性。另一方面,您可以实现接口(仅用于单元测试),并在单元测试中创建假对象。这种方法一开始看起来很不错,但当您试图使用这些赝品传输数据时,它会变得更加丑陋


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

我在TDD中做了几次错误的开始,试图解决同样的问题。对我来说,当我意识到我的导师所说的“我们不想测试框架”(在我们的例子中是.Net框架)的意思时,我取得了突破

在您的情况下,听起来好像您有一些与文件和数据库接口的业务逻辑。我要做的是尽可能在最薄的层中抽象文件和数据库逻辑。然后,您可以使用Mock(赝品或存根)来模拟文件和数据库层。这将允许您测试一些场景,比如如果我的数据库返回此类信息,那么我的业务逻辑是否正确处理了这些信息?同样,对于文件访问,您可以测试代码,找出要在哪个路径中打开哪个文件,并且可以测试您的逻辑是否能够正确地分离任何给定文件的内容,以及是否能够正确地使用它

例如,如果您的文件访问层由一个函数组成,该函数采用路径名和文件名,并以长字符串形式返回文件内容,那么您实际上不需要对其进行测试,因为基本上您只需对框架/操作系统进行一次调用,并且不会出现很多错误

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

用这种方式工作需要一些时间来适应,但一旦它在你的脑海中点击,它就绝对是多余的了


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

不要让硬东西妨碍你。。。如果由于数据库或文件集成的原因,它本身就很难测试,那么就暂时忽略它。最有可能的是,您可以使用带有依赖项注入等的mock将难以测试的内容重构为易于测试的内容。。。在那之前,测试简单的东西并建立一个好的单元测试套件。。。当您对难以测试的东西进行重构时,您将有一个更高的置信区间,即它不会破坏任何其他东西。。。重构使某些东西更容易测试是重构的一个很好的理由

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. 
当他们的类违反并且没有被使用时,人们会面临这个问题

有一条很好的规则,类应该只通过它们的公共方法/属性进行测试。如果其他人使用内部方法,则可以对其进行测试。私有或受保护的方法不应由于测试而成为内部方法

On the other hand, you could implement interfaces (only for the purpose of unit testing) and create fake objects within your unit tests.  
是的,由于模拟框架的限制,接口很容易模拟。 如果您可以创建一个类型的实例(伪/存根),那么您的依赖项不应该实现接口

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

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

  • 当我开始编写单元测试时,我从“对象母亲”开始。现在我正在使用“测试数据生成器”

    Michael Feathers的书中有很多好主意可以帮助你。

    可能重复的