Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock LDAP Laravel auth for unit testing

In my Laravel project I use Ldap-connector package to authenticate users against LDAP

Auth works fine out of the box.

In /app/providers/AuthServiceProvider.php I have a policy defined to manage LDAP user access, for example:

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 
    // ...
}

In the controller I check the policy for logged in user like:

class RewardController extends Controller {
    public function __construct($handler = null) {
        $this->authorize('rewards');
    }
    // other methods
    // ...
}

Everything works fine and if logged in user doesn't have Marketing or Admin group, the controller will throw 403 exception.

Now, for my phpunit tests I need to mock LDAP auth and provide the access to the controller to tests it's methods, otherwise policy throws me This action is unauthorized. error

Since ldap auth driver is implemented I don't think user model App/User is used and I can't just have it done with $this->actingAs($user) from Laravel docs from here

like image 912
Seva Kalashnikov Avatar asked Oct 30 '22 05:10

Seva Kalashnikov


1 Answers

I was able to find solution by myself

I switched LDAP connection package to Adldap2/Adldap2-Laravel

I used existing unit tests and created my own auth with Admin group user:

<?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'           => ['[email protected]'],
            '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]);

    }
}

This part adds Admin group to the user mock

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

$mockedBuilder->shouldReceive('newInstance')->andReturnSelf();
$mockedBuilder->shouldReceive('newCollection')->andReturn([$mockedGroup]);
like image 51
Seva Kalashnikov Avatar answered Nov 15 '22 06:11

Seva Kalashnikov