模仿在laravel 5.1单元测试中有很多关系

时间:2017-10-03 15:23:21

标签: php laravel mocking phpunit

对于laravel 5.1中的单元测试我试图测试Client模型的级联删除功能,该功能在设置了递归标志的情况下,还应该删除与客户端关联的所有用户。 我想使用模拟用户adn测试,只是调用用户的删除函数,所以我不必使用数据库,并在将来将相同的原则应用于其他测试。

目前测试失败,因为我无法找到一种方法使客户端模型在不触发查询的情况下检索关联用户。 我想我需要模拟客户端的hasMany关系定义函数,但我还没找到方法。

客户端模型:

class Client extends Model
{



    protected $table = 'clients';

    protected $fillable = [];



    public function casDelete($recursive = false){
        if($recursive) {
            $users = $this->users()->get();
            foreach($users as $user) {
                $user->casDelete($recursive);
            }
        }
        $this->delete();
    }

    public function users(){
        return $this->hasMany('App\User');
    }
}

用户模型:

class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
    use Authenticatable, CanResetPassword;

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'users';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['name', 'email', 'password', 'client_id'];

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = ['password', 'remember_token'];

    public function casDelete($recursive = false){
        $this->delete();
    }

    public function client(){
        return $this->belongsTo('App\Client');
    }

}

测试:

class ClientModelTest extends TestCase
{
    use DatabaseTransactions;

    function testCasDelete(){
    $client = factory(Client::class)->create();
    $user = factory(User::class)->make(['client_id' => $client->id]);

    $observer = $this->getMock('user');
    $observer->expects($this->once())->method('casDelete');

    $client->casDelete(true);


    }
}

1 个答案:

答案 0 :(得分:0)

使用DatabaseTransactions时,这意味着您要将数据持久化在数据库中。而且,当您从工厂使用create()时,您仍在使用数据库,因此,您根本不应该使用数据库,或者如果您想使用数据库,则只需解决问题即可。但是我建议的是这种解决方案,我没有在使用数据库init。

    $user = \Mockery::mock();
    $user->shouldReceive('casDelete')->andReturnNull();

    $queryMock = \Mockery::mock();
    $queryMock->shouldReceive('get')->andReturn([$user]);

    $clientMock = \Mockery::mock(Client::class)->makePartial();
    $clientMock->shouldReceive('users')->andreturn($queryMock);
    $clientMock->casDelete(true);

这样,您可以确保在每个用户模型上都调用了casDelete。 这是一个非常简单的测试用例,您可以根据需要实现的方式以自己喜欢的方式对其进行扩展。