【问题标题】:Mocking an Eloquent collection response from another mocked class模拟来自另一个模拟类的 Eloquent 集合响应
【发布时间】:2014-10-14 04:39:39
【问题描述】:

我在此处查看了许多关于堆栈溢出的相同思路的问题,以及其他地方但无法找到解决此特定问题的方法。

总的来说,我对单元测试还很陌生,所以对于有更多经验的人来说,这个错误可能(希望)是显而易见的。

问题来了:

我有一个 ResourceController,它使用依赖注入将一个类注入到构造函数中。

public function __construct(ResourceAPIInterface $api)
{

    $this->api = $api; 

}

当在控制器中调用该 API 时,注入的类会执行一些业务逻辑并返回一个 Eloquent 集合。

public function index($resource, $version)
{
    $input = Input::all();
    //Populate Data
    $data = $this->api->fetchAll($input);


    //Format response
    if($data->isEmpty()){
        //Format response
        $response = Response::make(" ", 204);
           }else {
        //Format response
        $response = Response::make($data, 200);
           }

    //Set content-type in header
    $response->header('Content-Type', 'application/json');
    $response->header('Cache-Control', 'max-age=3600');
    return $response;
}

从上面的代码可以看出,我需要响应是一个雄辩的响应,以便我可以测试它是否为空。 FetchAll 方法实际上只是返回表中所有记录的 Eloquent 排序规则。当我进行测试时,我可以毫无问题地模拟 API。但是,当我在嘲笑响应时,我真的希望响应是一个雄辩的集合,并且很难让它发挥作用。下面是一个测试示例:

            $course = Mockery::mock(new API\Entity\v1\Test);
    $this->mock->shouldReceive('fetchAll')->once()->andReturn($course->all());
    $this->mock->shouldReceive('name')->once()->andReturn('Course');

    // Act... 
    $response = $this->action('GET', 'ResourceController@show'); 

    // Assert... 
    $this->assertResponseOk(); 

上述方法有效,但是当我想对 show 方法进行相同的测试并模拟 ->first() 的雄辩响应时,我遇到了错误。

  1) ResourceControllerTest::testshow
   BadMethodCallException: Method Mockery_1_API_Entity_v1_Test_API_Entity_v1_Test::first() does not exist on this mock object

我尝试通过以下方式测试模型:

        $course = Mockery::mock('Eloquent', 'API\Entity\v1\Test');
           $response = $course->mock->shouldReceive('find')->with(1)->once()->andReturn((object)array('id'=>1, 'name'=>'Widget-name','description'=>'Widget description'));

但是,当我在测试中运行它时,我收到以下错误:

  1) ResourceControllerTest::testIndex
  BadMethodCallException: Method Mockery_1_API_Entity_v1_Test::getAttribute() does not exist on this mock object

关于如何解决此问题的任何想法?另外,如果有更好的方法来测试 eloquent 集合是否为空,这可能会解决我遇到的一些复杂性问题。

【问题讨论】:

    标签: unit-testing laravel-4 phpunit


    【解决方案1】:

    好的,我想出了如何使这项工作:

    public function testIndex($resource="course", $version="v1")
    {
        // Arrange... 
        $course = Mockery::mock('Eloquent', 'API\Entity\v1\Page')->makePartial();
        $course->shouldReceive('isEmpty')->once()->andReturn(false);
        $course->shouldReceive('all')->once()->andReturn($course);
        $this->mock->shouldReceive('fetchAll')->once()->andReturn($course->all());
    
        $this->mock->shouldReceive('name')->once()->andReturn('Course');
    
        // Act... 
        $response = $this->action('GET', 'ResourceController@index'); 
    
        // Assert... 
        $this->assertResponseOk(); 
    
    
    }
    

    我能够执行 PartialMock 来绕过 getAttribute() 错误。一旦我这样做了,我就开始收到错误:

    Call to undefined method stdClass::isEmpty() 
    

    所以我决定也模拟它,并将整个模拟对象传递给 all 命令的预期响应。

    然后在 API 类 $this->mock-> 的模拟中,我让它使用 ->all() 方法返回模拟的 eloquent 集合。

    这也适用于我为 find($id) 进行的其他测试。然而,那个不需要 isEmpty() 检查,所以更容易模拟。

    【讨论】:

      猜你喜欢
      • 2019-08-18
      • 2022-01-04
      • 1970-01-01
      • 2015-07-19
      • 2016-07-17
      • 1970-01-01
      • 2011-07-25
      • 1970-01-01
      • 2021-09-10
      相关资源
      最近更新 更多