Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何测试依赖于具有关系的雄辩模型的类?_Php_Unit Testing_Laravel_Eloquent_Mockery - Fatal编程技术网

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

Php 如何测试依赖于具有关系的雄辩模型的类?,php,unit-testing,laravel,eloquent,mockery,Php,Unit Testing,Laravel,Eloquent,Mockery,对于依赖于具有关系的雄辩模型的类,编写单元测试的最佳方法是什么?例如 真实对象(带有数据库)。这很容易,但很慢 真实对象(无数据库)。我可以创建一个新对象,但我不知道如何在不写入数据库的情况下设置相关模型 模拟对象。我遇到了一些问题,比如说,对有说服力的模型进行嘲弄(例如,见) 其他解决方案? 上下文:我将Laravel与一起用于访问控制。我想在单元测试中找到测试访问规则的最佳方法。这意味着我需要在测试期间将用户依赖项传递给权威机构。如果您正在编写单元测试,您不应该使用数据库。针对数据库的测

对于依赖于具有关系的雄辩模型的类,编写单元测试的最佳方法是什么?例如

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

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

  • 模拟对象。我遇到了一些问题,比如说,对有说服力的模型进行嘲弄(例如,见)

  • 其他解决方案?


上下文:我将Laravel与一起用于访问控制。我想在单元测试中找到测试访问规则的最佳方法。这意味着我需要在测试期间将用户依赖项传递给权威机构。

如果您正在编写单元测试,您不应该使用数据库。针对数据库的测试将被视为集成测试。看看罗伊·奥舍洛夫的

为了回答您的问题,(在没有深入研究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);
    }

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

一个权宜之计是使用内存中的SQLite数据库进行测试。我认为默认情况下,Laravel实际上会为您这样做,尽管您确实需要调用您的种子程序正在设置中。不知道它是否比MySQL数据库快(例如)但是当你确实需要一个真正的数据库时,这似乎是一种惯例。但是,是的,你真的应该尽可能多地模仿。我想有一件事需要考虑,那就是你的测试拥有的代码越多,它们在测试你的实际代码时的可靠性就越低,而不是你编写测试来模拟你的“真实”代码的能力。