如何模拟 LDAP Laravel 身份验证以进行单元测试
How to mock LDAP Laravel auth for unit testing
在我的 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
// ...
}
在控制器中,我检查登录用户的策略,例如:
class RewardController extends Controller {
public function __construct($handler = null) {
$this->authorize('rewards');
}
// other methods
// ...
}
一切正常,如果登录用户没有 Marketing
或 Admin
组,控制器将抛出 403
异常。
现在,对于我的 phpunit
测试,我需要模拟 LDAP 身份验证并提供对控制器的访问以测试它的方法,否则策略会抛出我 This action is unauthorized.
错误
自从实施了 ldap auth 驱动程序后,我不认为使用了用户模型 App/User
,我不能仅使用来自 Laravel 的文档 $this->actingAs($user)
来完成它 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
模拟
$mockedGroup = $this->mock(Group::class);
$mockedGroup->shouldReceive('getName')->once()->andReturn('Admin');
$mockedBuilder->shouldReceive('newInstance')->andReturnSelf();
$mockedBuilder->shouldReceive('newCollection')->andReturn([$mockedGroup]);
在我的 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
// ...
}
在控制器中,我检查登录用户的策略,例如:
class RewardController extends Controller {
public function __construct($handler = null) {
$this->authorize('rewards');
}
// other methods
// ...
}
一切正常,如果登录用户没有 Marketing
或 Admin
组,控制器将抛出 403
异常。
现在,对于我的 phpunit
测试,我需要模拟 LDAP 身份验证并提供对控制器的访问以测试它的方法,否则策略会抛出我 This action is unauthorized.
错误
自从实施了 ldap auth 驱动程序后,我不认为使用了用户模型 App/User
,我不能仅使用来自 Laravel 的文档 $this->actingAs($user)
来完成它 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
模拟
$mockedGroup = $this->mock(Group::class);
$mockedGroup->shouldReceive('getName')->once()->andReturn('Admin');
$mockedBuilder->shouldReceive('newInstance')->andReturnSelf();
$mockedBuilder->shouldReceive('newCollection')->andReturn([$mockedGroup]);