如何使用返回自身实例的方法来模拟别名类?

时间:2019-03-29 18:48:57

标签: php phpunit mockery

最近,我已经成功地将 Mockery 用于PHPUnit测试。但是,我正在工作的项目中存在一个依赖关系,该依赖关系使用静态方法调用与API进行交互。我正在努力测试一个特定的用例,感觉在开发路线图中会找到其他类似的用例。

以此类为例:

namespace Name\Space;
class User
{
    /**
     * @return \Name\Space\User[]
     */
    public static function list(): array
    {
        // ...
    }
    public static function create(array $attrs): User
    {
        // ...
    }
}

如果我只想断言一个方法返回原始类型,例如数组:

Mockery::mock('alias:\Name\Space\User')
    ->shouldReceive('list')
    ->andReturn([]);

工作正常,主要是因为我没有测试数组内容。

但是,我必须调用create方法,该方法返回类本身的一个实例(User)。如果我做这样的事情:

$user = new \Name\Space\User();
Mockery::mock('alias:\Name\Space\User')
    ->shouldReceive('create')
    ->andReturn($user);

显然,别名将不起作用,因为该类已经通过自动加载器(在这种情况下为composer)加载了。

有人对如何解决这个问题有建议吗?

2 个答案:

答案 0 :(得分:2)

如何在闭包中创建用户?

<?php

$user = Mockery::mock('overload:\Name\Space\User')
    ->shouldReceive('create')
    ->andReturnUsing(function() {
              return new \Name\Space\User();
    });

答案 1 :(得分:0)

模拟静态内容总是很痛苦的。 我建议创建一个调用静态API调用的Proxy对象,然后仅返回API结果并将该对象注入到您需要调用API的任何地方。

通过这种方式,只需模拟代理对象即可轻松进行测试。

然后可以在纯单元测试范围之外的端到端测试中测试代理对象本身。

您仍然可以像这样进行更具侵略性的工作 https://www.pagemachine.de/blog/mocking-static-method-calls/?cn-reloaded=1

但是编写不属于单元测试的代码纯粹是为了使某些东西可测试对我来说是不合适的。