如何在 Laravel 测试中模拟类的属性

Posted

技术标签:

【中文标题】如何在 Laravel 测试中模拟类的属性【英文标题】:How to mock a property of a class in Laravel tests 【发布时间】:2019-02-08 13:48:02 【问题描述】:

我在我的 laravel 5.6 应用程序中使用 ZipArchive 类来处理 zip 文件。在我的测试中,我为 ZipArchive 类创建了一个模拟,如下所示:

$this->zipArchiveMock = $this->createMock(ZipArchive::class);

我可以模拟 ZipArchive 类的方法,如下所示:

$this->zipArchiveMock->expects($this->once())
            ->method('open')
            ->will($this->returnValue(true));

我想模拟 ZipArchive 类的名为 numFiles 的属性。我试着做$this->zipArchiveMock->numFiles = 2。但$this->zipArchiveMock->numFiles 始终为 0。如何模拟 ZipArchive 类上的属性?

谢谢

【问题讨论】:

【参考方案1】:

好的,所以有 2 个选项,您可以使用 Mockery 模拟公共属性或模拟 count() 函数。

$this->zipArchiveMock->set('numFiles', 2);

(我不知道你是否使用 Mockery,但它包含在 Laravel 中,所以我假设你使用了) http://docs.mockery.io/en/latest/reference/public_properties.html

或者:

$this->zipArchiveMock->expects($this->once())
    ->method('count')
    ->will($this->returnValue(2));

编辑:

您使用的不是 Mockery,而是 phpunit。我找不到一种方法来模拟对象上的属性或使用 PHPUnit 在模拟上设置属性。相反,我建议你像这样使用 Mockery:

$this->zipArchiveMock = \Mockery::mock('ZipArchive');
$this->zipArchiveMock->set('numFiles', 2);

$this->zipArchiveMock->shouldReceive('open')
        ->once()
        ->andReturn(true);

希望这对你有用。

【讨论】:

感谢您的回复。我使用的是 PHP 7.1.21,ZipArchive 的 count() 函数仅在 7.2 中可用(参考:php.net/manual/en/ziparchive.count.php#123091)。所以我必须使用 numFiles 属性。我按照你的建议做了$this->zipArchiveMock->set('numFiles', 2);,但后来我收到错误Call to undefined method Mock_ZipArchive_90b9991f::set() 我刚刚发现您正在使用 PHPUnit 模拟。而且我找不到解决您的 PHPUnit 问题的方法。 set() 方法是一种嘲弄方法。所以我更新了我的问题以进一步解释 Mockery。

以上是关于如何在 Laravel 测试中模拟类的属性的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PHPUnit / Laravel 中模拟 JSON 文件

在 Laravel 中运行功能测试时如何模拟服务(或服务提供者)?

如果在Laravel 5.5单元测试中隐藏密码,如何模拟用户创建

如何在 laravel 5 中模拟模型上的 create 方法?

如何在 Laravel 中模拟验证规则

在 PHPUnit 中调用路由时如何在 Laravel 8 中模拟 Eloquent 模型