【问题标题】:How to handle endpoint calls testing with different permissions如何处理具有不同权限的端点调用测试
【发布时间】:2021-11-11 14:30:33
【问题描述】:

我有一个拥有大约 30 个权限的 Laravel 应用程序。 应用程序还使用大量端点。

现在我想为每个端点编写功能测试,检查每个端点的权限。

我的问题是: 我应该为每个权限编写单独的方法吗:


public function test_if_user_can_create_article_having_articles_index_permission()
{
    $user = $this->makeUserWithSuchPermisssion();
    $this->actingAs($user)->post('/articles')->assertStatus(403)
}

public function test_if_user_can_create_article_having_articles_create_permission()
{
    $user = $this->makeUserWithSuchPermisssion();
    $this->actingAs($user)->post('/articles')->assertStatus(201)
}

public function test_if_user_can_create_article_having_users_index_permission()
{
    $user = $this->makeUserWithSuchPermisssion();
    $this->actingAs($user)->post('/articles')->assertStatus(403)
}

等等

或者我应该通过循环遍历动作测试中的每个权限来做到这一点


public function test_if_user_can_create_article()
{
    foreach($invalid_permissions as $permission)
    {
        $user = $this->makeUserWithSuchPermisssion($permission);
        $this->actingAs($user)->post('/articles')->assertStatus(403)
    }
    

    foreach($ok_permissions as $permission)
    {
        $user = $this->makeUserWithSuchPermisssion($permission);
        $this->actingAs($user)->post('/articles')->assertStatus(201)
    }
    
}

或者我应该以其他方式吗?如果是,你是如何解决的? 我不想使用这样的每个权限对每个端点进行多次手动调用,因为它会变得非常难以维护。


public function test_if_user_can_create_article()
{
    $route = '/articles';

    $this->actingAs($this->createUserWithPermission('article.index'))->post($route)->assertStatus(403);
    $this->actingAs($this->createUserWithPermission('users.index'))->post($route)->assertStatus(403);
    $this->actingAs($this->createUserWithPermission('users.update'))->post($route)->assertStatus(403);
    $this->actingAs($this->createUserWithPermission('article.create'))->post($route)->assertStatus(201)->assertJson(['aaa' => 'bbb']);
    
}

【问题讨论】:

    标签: php laravel testing permissions phpunit


    【解决方案1】:

    最终由您决定! (不是您要寻找的)您应该测试能够为您的应用程序增加价值的功能。

    我个人会进行 2 次像这样的高阶测试来测试 1 个帐户在权限下工作,而 1 个帐户不起作用,然后在一些晦涩的测试中对检查模拟用户权限的函数进行单元测试。

    现在我无法准确回答您应该测试什么,因为我不知道您的权限是如何实现的。但是,如果您确实决定要测试每个权限(检查每个否定案例似乎是浪费时间),我会将所有失败案例组合到一个测试中并像您在第二个示例中所做的那样遍历它们,然后通过测试的另一个测试。

    还要确保在错误消息中添加失败的权限,这是->assertStatus(201, $permission_xyz_failed_message) 中的第二个参数,因为如果它有一个很好的理由开始失败,这将增加价值。

    【讨论】:

    • 感谢您的回复。我之前开发的应用程序是由非常缺乏经验的开发人员开发的。应用程序包含很多乱七八糟的东西,包括奇怪的、容易破坏的权限检查。这就是为什么我认为使用不同的权限调用每个端点会很好,因为这些端点中使用的can 策略很容易被破坏。而且因为应用程序正在燃烧几周......你知道;-)
    【解决方案2】:

    您的测试并不完全正常:

    • 命名约定是使用should 代替if 并使用when。例如,test_if_user_can_create_article_having_articles_index_permission 应该是 test_user_can_create_article_when_having_articles_index_permission
    • 永远不要在测试中做更多的测试。 test_if_user_can_create_article 不应该循环并测试所有内容(以及最坏的 2 种不同情况),因为如果只有一个失败,则整个测试都会失败,而且没有任何意义,因为所有其他测试都通过了,所以它应该只失败具体案例/测试。因此,要解决这个问题,请使用 @dataProvider 并创建 2 个不同的测试,一个断言它可以创建,一个断言它不能创建。
    • 与你的 XXXX 权限测试有关,完全没问题,这是一个特性测试,所以如果你以后更改该授权的实现,这个测试应该仍然通过,所以可以为每个案例创建 1 个测试. (我也会这样做)。
    • 与您的上一个问题有关,不要创建那种测试,准确地测试您想要的。在该示例中,如果有任何一个失败,您将无法确切知道是哪一个,如果这样做,您将在一个或多个案例的测试中失败,而其他案例通过,因此将每个案例拆分为单独的测试。

    【讨论】:

    • 是的,这就是我想要遵循的方式,但我真的很讨厌一遍又一遍地复制和粘贴相同的代码来涵盖每个端点的每个权限的所有情况。但看起来这是解决我的问题的唯一公平方法
    • 是的,这将是针对每个案例的功能测试。如果您的权限类型只是 string,您可以将该字符串发送到将创建用户的方法,然后测试您需要的任何 URL(也发送)。这就是您可以使用上面提到的@dataProviders 的方式。
    猜你喜欢
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 2019-05-15
    • 2020-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    相关资源
    最近更新 更多