Laravel 5模拟一个Eloquent模型

4

我在测试我的一个控制器时,无论我尝试什么方法,都会收到错误提示,说all()函数不存在。

Static method Mockery_1_App_Models_User::all() does not exist on this mock object

我的测试方法:

/**
 * Test index page
 * @return void
 */
public function testIndexAsUser()
{
    $this->beUser();

    // The method calls the mock objects should receive
    $this->user->shouldReceive('all')->once()->andReturn([]);

    // Call index page
    $response = $this->call('GET', 'users');

    // Assertions
    $this->assertResponseOk();
    $this->assertViewHas('user');
    $this->assertViewNameIs('users.show');
}

我的模拟方法:

/**
 * Mock a class
 * @param  string $class
 * @return Mockery
 */
public function mock($class)
{
    $mock = Mockery::mock('Eloquent', $class);

    app()->instance($class, $mock);

    return $mock;
}

我的实际控制器方法:

/**
 * Show all users
 * @return Response
 */
public function getIndex()
{
    $users = $this->user->all();

    return view('users.index');
}

我在模拟对象中使用的Eloquent类是否有误?自从 Laravel 5 版本,模型不再引用 Eloquent 类,而是引用 Illuminate\Database\Eloquent\Model,但我也尝试过这个。


1
很有可能这与 Laravel 5 还未进入 Beta 版本有关 - Laravel 5 的“测试”功能尚未完成。在 Taylor 完成 L5 的所有测试支持之前,不要花太多时间在此上面。 - Laurence
你尝试过 Mockery::mock('Model', $class) 或者 Mockery::mock('App\Model', $class) 了吗?(我知道你说过你试过使用完整的命名空间,但是你试过短版本的吗?) - Laurence
1个回答

3

最简单的模拟 Eloquent 模型的方法是使用部分模拟:

$mock = m::mock('MyModelClass')->makePartial();

然而,由于您正在使用静态方法(all()),因此这些并没有什么用处。PHP的非常严格的性质使得您可以以非静态的方式调用静态方法($user->all()),但您应该避免这样做。相反,您应该采取更加严谨的方式:

$users = $this->user->newQuery()->get();

这可以被模拟:

$mockUser->shouldReceive('newQuery->get')->andReturn([/*...*/]);

如果您希望进一步进行,可以将 get() 调用移到单独的存储库类中,并将其注入到控制器中,这将使模拟更加容易。您可以在网上找到许多关于存储库模式的文章。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接