Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.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
Unit testing 依赖注入、单元测试和信息隐藏_Unit Testing_Dependency Injection_Information Hiding - Fatal编程技术网

Unit testing 依赖注入、单元测试和信息隐藏

Unit testing 依赖注入、单元测试和信息隐藏,unit-testing,dependency-injection,information-hiding,Unit Testing,Dependency Injection,Information Hiding,假设您有一个具有类型为Bar的私有成员的类Foo。您不希望用户知道Foo的实现包含一个Bar,您也不希望用户能够创建自己的Bar并通过Foo的构造函数、任何其他方法或配置文件传递它 编辑:Bar也有问题,因为它访问测试环境无法控制的资源,如特殊数据库、网络连接或其他进程 当您还希望能够对Foo进行单元测试时,您会怎么做?依赖注入仍然可行吗?这是否意味着Bar和Foo的耦合过于紧密(即使依赖是单向的),并且这种情况永远不会被接受?如果Bar类型只是Foo的一个实现细节,那么您的单元测试就不需要担心

假设您有一个具有类型为Bar的私有成员的类Foo。您不希望用户知道Foo的实现包含一个Bar,您也不希望用户能够创建自己的Bar并通过Foo的构造函数、任何其他方法或配置文件传递它

编辑:Bar也有问题,因为它访问测试环境无法控制的资源,如特殊数据库、网络连接或其他进程


当您还希望能够对Foo进行单元测试时,您会怎么做?依赖注入仍然可行吗?这是否意味着Bar和Foo的耦合过于紧密(即使依赖是单向的),并且这种情况永远不会被接受?

如果Bar类型只是Foo的一个实现细节,那么您的单元测试就不需要担心创建Bar,因为它们无论如何都应该只使用Foo的公共接口

编辑:如果Bar访问外部资源,那么我将使其成为Foo的显式依赖项,然后要求将一个实例传递到Foo的构造函数中,以便在单元测试中轻松模拟。

[免责声明:我在工作]

你有三种选择:

  • 创建一个设置Bar类的内部方法-使用assemblyInf.cs文件中的InternalVisibleTo,您可以启用测试来设置该类
  • 在测试过程中,使用DI注入Bar类,使用伪类或伪类更改该类
  • 使用类似Typemock Isolator(.NET)的伪造/模拟框架,使您能够使用
    Isolate.Swap.NextInstance.With(fakeBar)在另一个类中创建的对象上设置伪造行为

  • 如果可以的话,您永远不想隐藏依赖项

    如果是您的代码,您应该通过重新设计
    Bar
    来明确依赖关系,以接受昂贵资源生成的对象,而不是直接访问昂贵资源:将数据库访问代码(或其他任何代码)从
    Bar
    移动到
    Foo
    ,您可以在其中插入测试双精度


    如果这不实用(即,您正在处理其他人的类),则非常好。

    您的问题不是需要访问私人成员。这只是一个事实的征兆,即所讨论的类不是被设计为孤立的。它只允许一种非常特定的用法,即
    new
    将对象添加到昂贵的资源中

    即使你成功地破解了不稳定的设计,你仍然只会做集成测试。单元测试是关于隔离的,与集成相反。由于该类不能被隔离,根据定义,您不能对其进行单元测试

    是否有理由认为外部化依赖是不可取的?这个对象如何使其免于像其他对象一样被注入依赖项

    编辑


    我当然意识到你可以用一些诡计来孤立它。然而,这些技术绕过了公共接口,限制了未来的灵活性,并增加了有人破坏它的可能性(基本上,取消了私有成员的有用性)。

    好的,我的问题太模糊了(编辑)如果Bar访问互联网或数据库,会发生什么?你仍然需要伪造/模拟/存根它+1:如果Bar完全隐藏,它不是真正可测试的,是吗?如果它有外部依赖项,则不应将其隐藏。任何隐藏条的尝试都是一种糟糕的设计。内部方法思想+1。。不幸的是,并非所有语言都支持java等内部方法。我想不出一个方法来完成依赖注入。。也许通过适配器设计模式?你能提供一个例子吗?事实证明java在包级别有内部访问,所以我错了。或者你可以将构造函数设置为内部(同样,在.NET中使用InternalsVisibleToAttribute)并提供一个公共工厂。除非我在设计一个面向公众的API时考虑到安全问题,否则我不会费心@平淡无奇-你在使用什么语言?目前是java,但这个问题可能发生在任何语言中:)接受答案,但如果有人决定提供一些依赖注入示例(没有构造函数或配置文件),我将不胜感激。+1:设计(完全隐藏栏)是个坏主意。+1:隐藏栏是个坏主意。