Laravel:如何模拟依赖项注入类方法 [英] Laravel: how to mock dependency injection class methods

查看:169
本文介绍了Laravel:如何模拟依赖项注入类方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过 GitHub API ://github.com/GrahamCampbell/Laravel-GitHub"rel =" nofollow noreferrer> Laravel API包装器.我创建了一个依赖注入类.如何在App\Http\GitHub.php类中模拟exists方法?

I'm using the GitHub API through a Laravel API Wrapper. I've created a dependency injection class. How can I mock the exists method within the App\Http\GitHub.php class?

App\Http\GitHub.php:

use GrahamCampbell\GitHub\GitHubManager;

class Github
{
    public $username;

    public $repository;

    public function __construct($username, $repository, GitHubManager $github)
    {
        $this->username = $username;

        $this->repository = $repository;

        $this->github = $github;
    }

    public static function make($username, $repository)
    {
        return new static($username, $repository, app(GitHubManager::class));
    }

    /**
     * Checks that a given path exists in a repository.
     *
     * @param  string  $path
     * @return bool
     */
    public function exists($path)
    {
        return $this->github->repository()->contents()->exists($this->username, $this->repository, $path);
    }
}

测试:

    use App\Http\GitHub;
    public function test_it_can_check_if_github_file_exists()
    {
        $m = Mockery::mock(GitHub::class);
        $m->shouldReceive('exists')->andReturn(true);
        app()->instance(GitHub::class, $m);

        $github = GitHub::make('foo', 'bar');

        $this->assertTrue($github->exists('composer.lock'));
    }

运行此测试实际上会命中API,而不仅仅是返回模拟的true值,我在这里做错什么了吗?

Running this test actually hits the API rather than just returning the mocked true value, what am I doing wrong here?

推荐答案

此处存在树问题,即实例化对象的方式.在模拟对象上调用两个方法并将其绑定到错误实例的方式.

There is tree problems here, the way you instantiate your object. The way you are calling two methods on your mock object and you are binding it to the wrong instance.

依赖注入

静态方法通常是一种反模式,构造函数参数与容器的工作方式不兼容,因此您将无法使用resolve(Github::class);.通常,Laravel类通过使用setter来解决此问题.

Static methods in general is an anti pattern and constructor parameters does not work with how the container works, therefor you would not be able to use resolve(Github::class);. Usually Laravel classes solve this by using setters.

class Github
{
    public $username;

    public $repository;

    public $github;

    public function __construct(GitHubManager $github)
    {
        $this->github = $github;
    }

    public function setUsername(string $username) {
        $this->username = $username;

        return $this;
    }

    public function setRepository(string $repository) {
        $this->repository = $repository;

        return $this;
    }
}

现在,您可以使用以下方法来调用代码.

Now you can call your code with the following approach.

resolve(Github::class)->setUsername('Martin')->setRepository('my-repo')->exists();

方法链

这里有两个对模拟对象的调用,它们是链接的,因此您应该创建一个与此相似的模拟链.现在,模拟对象将不知道内容,因此会失败.

Here there are two calls to the mock object, they are chaining, so you should create a mock chain similar to this. Right now the mock object would not know contents and therefor fail.

$m = Mockery::mock(GitHub::class);

$m->shouldReceive('contents')
    ->andReturn($m);

$m->shouldReceive('exists')
    ->with('Martin', 'my-repo', 'your-path')
    ->once()
    ->andReturn(true);

绑定实例

使用容器,它将基于类自动加载它,因此,如果使用app()resolve()或在构造函数中进行解析,则以下代码将依赖注入GithubManager.

Working with the container, it will automatically load it based on the classes, so the following code will dependency inject GithubManager if resolved with app(), resolve() or in a constructor.

public function __construct(GithubManager $manager)

此代码将在上面的我的解析示例中注入GithubManager,但是在您的示例中,您将其绑定到GitHub类,该类不会自动加载,并且您应始终对链中最远的类进行模拟.因此,实例绑定应该是.

This code will inject GithubManager in my resolve example above, but in your example you are binding it to the GitHub class, which wont automatically load and you should always mock the class farthest down the chain. Therefor you instance bind should be.

app()->instance(GitHubManager::class, $m);

这篇关于Laravel:如何模拟依赖项注入类方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆