Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/264.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
Php 试验工厂法_Php_Unit Testing_Phpunit - Fatal编程技术网

Php 试验工厂法

Php 试验工厂法,php,unit-testing,phpunit,Php,Unit Testing,Phpunit,编写测试以覆盖100%的代码是我们应该尝试实现的目标。但我想到了我不知道如何测试方法(工厂方法)的情况: 该方法的目的是创建文档的快捷方式,无需每次写3行 如何测试这种方法 或者这就是为什么我们有@codecoverageignostart块的原因?正是出于这个原因,PHPUnit不提供这种注释 编辑: 这种方法背后的主要思想是让客户的生活更轻松。没有更多,没有配置等(但该方法将是一个很好的地方) 也许我应该考虑一下,如果我真的应该提供那个方法,想要使用文档的用户应该知道依赖关系,它不应该被隐

编写测试以覆盖100%的代码是我们应该尝试实现的目标。但我想到了我不知道如何测试方法(工厂方法)的情况:

该方法的目的是创建文档的快捷方式,无需每次写3行

如何测试这种方法

或者这就是为什么我们有@codecoverageignostart块的原因?正是出于这个原因,PHPUnit不提供这种注释


编辑: 这种方法背后的主要思想是让客户的生活更轻松。没有更多,没有配置等(但该方法将是一个很好的地方)

也许我应该考虑一下,如果我真的应该提供那个方法,想要使用文档的用户应该知道依赖关系,它不应该被隐藏。

文档
设置
文件系统
)通过构造函数,然后根据需要使用


再重新考虑一下你的100%覆盖率政策,这绝对不是一件好事。

我发现答案有点像:这段代码是不可测试的

无论您在测试的方法中有新的XXX(…),您都注定要失败

更多:

将依赖项传递给工厂方法,初始化内部的新对象,并正确配置它。在测试中,依赖项将是模拟而不是真实对象

方法1

传递允许创建依赖项的工厂:

public function getDocument(SettingsFactory $sf, FilesystemFactory $ff){
    $document = new Document();
    $document->settings($sf->getSettings());
    $document->filesystem($ff->getFilesystem());
    return $document;
}
public function getDocument(Settings $settings, Filesystem $filesystem) {
    $document = new Document();
    $document->settings($settings);
    $document->filesystem($filesystem);
    return $document;
}
在测试中,您应该:

  • 创建
    Settings
    instance或mock和一个
    SettingsFactory
    mock,该mock需要调用
    getSettings
    ,并返回
    Settings
    实例
  • 创建
    Filesystem
    实例或mock和一个
    filesystemfactory
    mock,该mock需要调用
    getFilesystem
    ,并将返回
    Filesystem
    实例
  • 调用
    DocumentFactory
    方法,传递工厂。检查是否返回了
    文档
    对象
  • 检查分配给
    文档
    的对象是否与配置模拟返回的对象相同
这方面的变体将
getSettings
getFilesystem
作为
文档
工厂的方法。在这种情况下,您应该创建工厂的部分模拟,并对其设置期望值。因此调用了真正的
getDocument
方法,但是当调用
getSettings
getFilesystem
方法时,返回受控实例

方法2

传递实际依赖项:

public function getDocument(SettingsFactory $sf, FilesystemFactory $ff){
    $document = new Document();
    $document->settings($sf->getSettings());
    $document->filesystem($ff->getFilesystem());
    return $document;
}
public function getDocument(Settings $settings, Filesystem $filesystem) {
    $document = new Document();
    $document->settings($settings);
    $document->filesystem($filesystem);
    return $document;
}
在测试中,您应该:

  • 创建
    设置
    实例或模拟
  • 创建
    文件系统
    实例或模拟
  • 调用
    DocumentFactory
    方法,传递
    设置
    文件系统
    。检查是否返回了
    文档
    对象
  • 检查分配给
    文档
    的对象是否与传递给factory方法的实例相同

此方法的作用是什么?返回初始化的
文档
对象。因此,您只需验证返回的值是否为
文档
实例,以及是否设置了
设置
文件系统
对象。如果您有这些的getter,那么很容易,否则您必须访问相应的属性

这个测试听起来很基本,但它确实测试了它需要测试的东西。当您以注入设置和文件系统的方式重构代码时,测试仍然会告诉您文档是否设置了这些属性


它被称为
单元测试
,因为您测试的是
单元
,而不是对象或方法。如果你的单位有多个班级,就让它去吧。不需要所有的东西都被注入,也不需要所有的东西都被模仿——这些东西易于测试,但在某些情况下,最好不要模仿它们

有什么问题?对于这个方法,需要测试文档是否有明确的设置和文件系统。但在单元测试中,我们不应该依赖依赖依赖项,所以即使设置或文件系统类尚未定义,测试也应该通过。@tne说的是正确的答案。阅读关于依赖性注射。好的,我明白你们的意思,这将允许我测试方法。但我每次创建文档时都需要新的实例。你的想法很好,我理解。感谢您写下答案,一般来说,您的解决方案类似于那些表单注释I链接:(请再次执行此操作:)。我编辑了我的问题,请看。依赖注入可以通过使用一些库来管理:@SonnyD如果你认为答案解决了你的问题,那么你应该礼貌地接受最好的答案,同时也可以帮助这个问题的未来观众知道正确的解决方案是什么。我跳过测试这个方法。但我可能会使用断言。我没有用于文件系统设置的getter,因为它们不应该从文档中访问。为了检查它,我将使用ReflectionClass。至于第二部分,我不知道……在我对单元测试的思考中(可能是错误的),我们不应该使用依赖项的原始实现(这就是我想要摆脱的),所有这些都应该被模仿(存根,伪造)。我们正在测试“单元”,但必须在单独的环境中进行测试,我们可以轻松地进行配置。测试这个特定的“单元”应该通过测试,而不需要测试“单元”之外的任何东西。@SonnyD我建议你阅读Steve Freeman的书(或者更好,他写的书《由测试引导的面向对象软件的成长》),这是(真正的)很好的建议。我认为是否模拟和是否反转依赖关系(例如注入)的问题是完全不同的。我建议OP对API进行评估,以决定是否将其置于适配器之后(如果可以最小化API,则建议使用模拟库,否则只要接口稳定且最小,则使用模拟库可能更合适)。我同意你的看法