如何测试依赖于具有关系的Eloquent模型的类?

时间:2014-04-07 10:48:28

标签: php unit-testing laravel eloquent mockery

为类编写单元测试的最佳方法是什么,这取决于具有关系的Eloquent模型? E.g。

  • 真实对象(带数据库)。这很容易,但很慢。

  • 真实对象(无数据库)。我可以创建一个新对象,但我无法在不写入数据库的情况下查看如何设置相关模型。

  • 模拟对象。我使用Mockery和Eloquent模型遇到了问题(例如见this question)。

  • 其他解决方案?

上下文:我使用Laravel与 Authority RBAC 进行访问控制。我想找到在单元测试中测试访问规则的最佳方法。这意味着我需要在测试期间将用户依赖项传递给Authority。

1 个答案:

答案 0 :(得分:0)

如果您正在编写单元测试,则不应使用数据库。对数据库的测试将被视为集成测试。查看Roy Osherove的videos

要回答你的问题,(并没有深入研究权限RBAC,我会做这样的事情:

// assuming some RBAC class
SomeRBACClass extends RBACBaseClass {

     function validate(UserClass $user) {
         if (!$roles = $user->getRoles())
         {
             return false;
         }

         $allowed = array('admin', 'superadmin');

         foreach ($roles as $role) {
             if (in_array($role->name, $allowed)) {
                 return true;
             }
         }

         return false;
     }

}

SomeRBACClassTest extends TestCase {

    function test_validate_WhenPassedUser_callsGetRolesOnUserWithNoArgs()
    {
        $rbac = new SomeRBACClass();
        $user = Mockery::mock('UserClass');

        $user->shouldReceive('getRoles')->once()->withNoArgs();

        $rbac->validate($user);
    }

    function test_validate_getRolesOnUserReturnsCollectionOfRoles_CallsGetAttributeWithNameOnFirstRole() {
        $rbac = new SomeRBACClass();
        $user = Mockery::mock('UserClass');
         // assuming $user->getRoles() returns a collection
        $collection = new \Illuminate\Support\Collection(array(
             $role1 = Mockery::mock('Role'),
             $role2 = Mockery::mock('Role'),
        ));
        $user->shouldReceive('getRoles')->andReturn($collection);

        $role1->shouldReceive('getAttribute')->once()->with('name');

        $rbac->validate($user);
    }

    function test_validate_getAttributeWithNameOnRoleReturnsValidRole_ReturnsTrue() {
        $rbac = new SomeRBACClass();
        $user = Mockery::mock('UserClass');
         // assuming $user->getRoles() returns a collection
        $collection = new \Illuminate\Support\Collection(array(
             $role1 = Mockery::mock('Role'),
             $role2 = Mockery::mock('Role'),
        ));
        $user->shouldReceive('getRoles')->andReturn($collection);
        $role1->shouldReceive('getAttribute')->andReturn('admin');

        $result = $rbac->validate($user);

        $this->assertTrue($result);
    }

这不是我要编写的所有单元测试的完整示例,但它是一个开始。例如,我还将验证当没有返回任何角色时,结果为false。