为依赖于具有关系的 Eloquent 模型的类编写单元测试的最佳方法是什么? 例如
-
真实对象(带数据库)。这很容易,但很慢。
-
真实对象(无数据库)。我可以创建一个新对象,但我看不到如何在不写入数据库的情况下设置相关模型。
-
模拟对象。我在使用带有雄辩模型的嘲弄时遇到了问题(例如,请参阅此问题)。
-
其他解决方案?
上下文:我正在使用带有权限 RBAC 的 Laravel进行访问控制。我想找到在单元测试中测试访问规则的最佳方法。这意味着我需要在测试期间将用户依赖项传递给 Authority。
如果你正在编写单元测试,你不应该使用数据库。针对数据库进行测试将被视为集成测试。查看Roy Osherove的视频。
为了回答你的问题,(并且没有深入研究权威 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。