模拟Laravel控制器依赖

har*_*ryg 5 php phpunit unit-testing laravel

在我的Laravel应用程序中,我有一个控制器,其中包含显示特定资源的方法.例如,说url是/widgets/26我的控制器方法可能会这样工作:

Class WidgetsController {
    protected $widgets;

    public function __construct(WidgetsRepository $widgets)
    {
        $this->widgets = $widgets;
    }

    public function show($id)
    {
        $widget = $this->widgets->find($id);

        return view('widgets.show')->with(compact('widget'));
    }
}
Run Code Online (Sandbox Code Playgroud)

我们可以看到我WidgetsControllerWidgetsRepository依赖.在该show方法的单元测试中,如何模拟此依赖项,以便我实际上不必调用存储库而只是返回硬编码widget

单元测试开始:

function test_it_shows_a_single_widget()
{
    // how can I tell the WidgetsController to be instaniated with a mocked WidgetRepository?
    $response = $this->action('GET', 'WidgetsController@show', ['id' => 1]);

    // somehow mock the call to the repository's `find()` method and give a hard-coded return value
    // continue with assertions
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*kes 15

您可以模拟存储库类并将其加载到IoC容器中.

所以当Laravel到达你的控制器时,它会发现它已经在那里并将解析你的模拟而不是实例化一个新模拟器.

function test_it_shows_a_single_widget()
{
    // mock the repository
    $repository = Mockery::mock(WidgetRepository::class);
    $repository->shouldReceive('find')
        ->with(1)
        ->once()
        ->andReturn(new Widget([]));

    // load the mock into the IoC container
    $this->app->instance(WidgetRepository::class, $repository);

    // when making your call, your controller will use your mock
    $response = $this->action('GET', 'WidgetsController@show', ['id' => 1]);

    // continue with assertions
    // ...
}
Run Code Online (Sandbox Code Playgroud)

类似的设置已经过测试,在Laravel 5.3.21中运行良好.


小智 3

Laracasts 上也有类似的问题。这个人有这样的事情(https://laracasts.com/discuss/channels/general-discussion/mockery-error?page=1):

public function testMe()
{
    // Arrange
    $classContext = Mockery::mock('\FullNamespace\To\Class');
    $classContext->shouldReceive('id')->andReturn(99);
    $resources = new ResourcesRepo($classContext);

    // Act

   // Assert
}
Run Code Online (Sandbox Code Playgroud)

但是,如果使用 PHPUnit 方法( http://docs.mockery.io/en/latest/reference/phpunit_integration.html ) ,您也可以将其放在 setUp 方法上。

希望这有帮助。