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数据库快(例如)但是当你确实需要一个真正的数据库时,这似乎是一种惯例。但是,是的,你真的应该尽可能多地模仿。我想有一件事需要考虑,那就是你的测试拥有的代码越多,它们在测试你的实际代码时的可靠性就越低,而不是你编写测试来模拟你的“真实”代码的能力。