【问题标题】:Mocking Laravel controller dependency模拟 Laravel 控制器依赖
【发布时间】:2015-10-21 15:52:02
【问题描述】:

在我的 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'));
    }
}

我们可以看到我的WidgetsController 有一个WidgetsRepository 依赖项。在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
}

【问题讨论】:

    标签: php unit-testing laravel phpunit


    【解决方案1】:

    您可以模拟存储库类并将其加载到 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
        // ...
    }
    

    类似的设置已经在 Laravel 5.3.21 中进行了测试并且运行良好。

    【讨论】:

      【解决方案2】:

      在 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
      }
      

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

      希望这有帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-05
        • 2022-01-09
        • 2019-12-25
        • 2011-06-15
        • 1970-01-01
        • 1970-01-01
        • 2017-01-08
        • 1970-01-01
        相关资源
        最近更新 更多