【问题标题】:Laravel & Mockery - Unit Testing Relational DataLaravel & Mockery - 单元测试关系数据
【发布时间】:2014-07-08 19:55:58
【问题描述】:

我有一个帖子和一个博客类。

从下面可以看出,Posts 类依赖于 Blog 类。

public function index(Blog $blog) {
    $posts = $this->post->all()->where('blog_id', $blog->id)->orderBy('date')->paginate(20);
    return View::make($this->tmpl('index'), compact('blog', 'posts'));
}

这个动作的url如下:

http://example.com/blogs/[blog_name]/posts

我正在尝试对此进行测试,但遇到了问题。

这是我的测试类 PostTestController:

public function setUp() {
    parent::setUp();
    $this->mock = Mockery::mock('Eloquent', 'Post');
}

public function tearDown() {
    Mockery::close();
}

public function testIndex() {

    $this->mock->shouldReceive('with')->once();

    $this->app->instance('Post', $this->mock);

    // get posts url
    $this->get('blogs/blog/posts'); //this is where I'm stuck.

    $this->assertViewHas('posts');
}

问题是……当 get 本身包含基于数据的变量输出时,如何测试 get 调用? 如何正确测试?

【问题讨论】:

    标签: php laravel phpunit mockery


    【解决方案1】:

    首先,您的代码中有错误。你可以删除 all()。

    $posts = $this->post
      ->where('blog_id', $blog->id)
      ->orderBy('date')
      ->paginate(20);
    

    其次,我不知道如何对路由模型绑定进行单元测试,所以我将public function index(Blog $blog) 更改为public function index($blogSlug),然后执行$this->blog->where('slug', '=', $blogSlug)->first() 或类似的操作。

    第三,只需执行m::mock('Post'),删除 Eloquent 位。如果您遇到此问题,请执行m::mock('Post')->makePartial()

    如果您想完全测试所有内容,大致如下所示。

    use Mockery as m;
    
    /** @test */
    public function index()
    {
        $this->app->instance('Blog', $mockBlog = m::mock('Blog'));
        $this->app->instance('Post', $mockPost = m::mock('Post'));
        $stubBlog = new Blog(); // could also be a mock
        $stubBlog->id = 5;
        $results = $this->app['paginator']->make([/* fake posts here? */], 30, 20);
        $mockBlog->shouldReceive('where')->with('slug', '=', 'test')->once()->andReturn($stubBlog);
        $mockPost->shouldReceive('where')->with('blog_id', '=', 5)->once()->andReturn(m::self())
            ->getMock()->shouldReceive('orderBy')->with('date')->once()->andReturn(m::self())
            ->getMock()->shouldReceive('paginate')->with(20)->once()->andReturn($results);
    
        $this->call('get', 'blogs/test/posts');
        // assertions
    }
    

    这是一个很好的例子,很难对与数据库层耦合的层进行单元测试(在这种情况下,您的 Blog 和 Post 模型是数据库层)。相反,我会设置一个测试数据库,用虚拟数据为其播种并在其上运行测试,或者将数据库逻辑提取到存储库类,将其注入控制器并模拟它而不是模型。

    【讨论】:

      猜你喜欢
      • 2013-09-08
      • 2015-03-07
      • 2014-03-15
      • 2013-05-26
      • 2019-12-11
      • 2014-09-19
      • 2019-04-15
      • 2018-03-14
      • 2021-03-26
      相关资源
      最近更新 更多