unit-testing - 如何模拟 LDAP Laravel 身份验证进行单元测试

标签 unit-testing laravel mocking phpunit laravel-5.2

在我的 Laravel 项目中,我使用 Ldap-connector package根据 LDAP 对用户进行身份验证

Auth 开箱即用。

在/app/providers/AuthServiceProvider.php 我定义了一个策略来管理 LDAP 用户访问,例如:

public function boot(GateContract $gate)
{
    $this->registerPolicies($gate);

    $gate->define('rewards', function ($user) {
        return ($user->getAdLDAP()->inGroup('Admin') || $user->getAdLDAP()->inGroup('Marketing')) ? true : false;
    });
    // other policies 
    // ...
}

在 Controller 中,我检查登录用户的策略,例如:
class RewardController extends Controller {
    public function __construct($handler = null) {
        $this->authorize('rewards');
    }
    // other methods
    // ...
}

一切正常,如果登录用户没有 MarketingAdmin组, Controller 会抛出403异常(exception)。

现在,对于我的 phpunit测试我需要模拟 LDAP 身份验证并提供对 Controller 的访问以测试它的方法,否则策略会抛出我 This action is unauthorized.错误

由于实现了 ldap auth 驱动程序,我认为用户模型 App/User被使用,我不能只用 $this->actingAs($user) 来完成它来自 Laravel 文档来自 here

最佳答案

我能够自己找到解决方案

我换了 LDAP连接包到 Adldap2/Adldap2-Laravel

我用过 existing unit tests并使用 Admin 创建了我自己的身份验证群组用户:

<?php

use Adldap\Auth\Guard;
use Adldap\Connections\Manager;
use Adldap\Connections\Provider;
use Adldap\Contracts\Connections\ConnectionInterface;
use Adldap\Laravel\Facades\Adldap;
use Adldap\Models\User;
use Adldap\Query\Builder;
use Adldap\Schemas\Schema;
use Adldap\Search\Factory;
use Illuminate\Support\Facades\Auth;
use Adldap\Models\Group;

class TestCase extends Illuminate\Foundation\Testing\TestCase
{
    public function pass_auth() {

        $mockedProvider = $this->mock(Provider::class);
        $mockedBuilder = $this->mock(Builder::class);
        $mockedSearch = $this->mock(Factory::class);
        $mockedAuth = $this->mock(Guard::class);
        $mockedConnection = $this->mock(ConnectionInterface::class);

        $mockedConnection->shouldReceive('isBound')->once()->andReturn(true);

        $mockedBuilder->shouldReceive('getSchema')->once()->andReturn(Schema::get());
        $mockedBuilder->shouldReceive('getConnection')->once()->andReturn($mockedConnection);

        $adUser = (new User([], $mockedBuilder))->setRawAttributes([
            'samaccountname' => ['jdoe'],
            'mail'           => ['jdoe@email.com'],
            'cn'             => ['John Doe'],
        ]);

        $manager = new Manager();
        $manager->add('default', $mockedProvider);

        Adldap::shouldReceive('getManager')->andReturn($manager);

        $mockedProvider->shouldReceive('search')->once()->andReturn($mockedSearch);
        $mockedProvider->shouldReceive('getSchema')->andReturn(Schema::get());
        $mockedProvider->shouldReceive('auth')->once()->andReturn($mockedAuth);

        $mockedSearch->shouldReceive('users')->once()->andReturn($mockedSearch);
        $mockedSearch->shouldReceive('select')->once()->andReturn($mockedBuilder);

        $mockedBuilder->shouldReceive('whereEquals')->once()->andReturn($mockedBuilder);
        $mockedBuilder->shouldReceive('first')->once()->andReturn($adUser);

        $mockedAuth->shouldReceive('attempt')->once()->andReturn(true);

        $this->assertTrue(Auth::attempt(['username' => 'jdoe', 'password' => '12345']));

        $mockedGroup = $this->mock(Group::class);
        $mockedGroup->shouldReceive('getName')->once()->andReturn('Admin');

        $mockedBuilder->shouldReceive('newInstance')->andReturnSelf();
        $mockedBuilder->shouldReceive('newCollection')->andReturn([$mockedGroup]);

    }
}

本部分添加Admin群到user mock
$mockedGroup = $this->mock(Group::class);
$mockedGroup->shouldReceive('getName')->once()->andReturn('Admin');

$mockedBuilder->shouldReceive('newInstance')->andReturnSelf();
$mockedBuilder->shouldReceive('newCollection')->andReturn([$mockedGroup]);

关于unit-testing - 如何模拟 LDAP Laravel 身份验证进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36729597/

相关文章:

Laravel 查询 - 提取 JSON 列中对象数组中的特定字段并计算

java - 使用 Mockito 模拟静态方法

angular - getTestBed 和 TestBed 的区别

unit-testing - 使用嵌入式容器测试 EJB 3.1 应用程序

laravel - 如果 id 为 null,如何在关系上运行 updateOrCreate

php - 如何在 laravel Controller 中检索 form.serialize() 数据

unit-testing - 如何避免 JUnit 测试中的多个断言?

java - 从 Scratch 对未测试代码执行单元和集成测试的方法

mocking - 使用 axios 拦截器模拟 axios

mocking - Jest 模拟全局 navigator.onLine