嘲笑来自另一个模拟类的Eloquent集合响应

时间:2014-08-20 17:44:40

标签: unit-testing laravel-4 phpunit

我已经在堆栈溢出的同一个思路上看了很多问题,而在其他地方却无法找到解决这一特定问题的方法。

我对单元测试一般都很新,所以对于有经验的人来说,这个错误可能(希望)是显而易见的。

问题在于:

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

public function __construct(ResourceAPIInterface $api)
{

    $this->api = $api; 

}

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

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

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

1 个答案:

答案 0 :(得分:0)

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

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()方法的模拟雄辩集合。

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