Lumen-framework: Unit Tests: User credentials cached between different requests.

Created on 29 Mar 2017  路  5Comments  路  Source: laravel/lumen-framework

When running a unit-test that involves sending multiple requests with different authorization credentials (ie, a single test involving multiple users), the AuthServiceProvider is only invoked for the 1st request. The user information is cached and re-used for all subsequent requests even if the credentials change.

For the example below,

  • Requests are sent with a Bearer authorization header containing a UserId.
  • The AuthServiceProvider just extracts the UserId from the Bearer authorization header.
  • The Controller validates that UserId in header matches the $request->user() value.

Unit-test:

    public function testAction()
    {
       // User1 performs action
       $headers1 = [ 'Authorization' => 'Bearer User1' ];
       $this->call( 'GET', '/test', [], [], [],
             $this->transformHeadersToServerVars( $headers1 ), null );
       $this->seeStatusCode( 200 );

       // User2 performs action
       $headers2 = [ 'Authorization' => 'Bearer User2' ];
       $this->call( 'GET', '/test', [], [], [],
             $this->transformHeadersToServerVars( $headers2 ), null );
       $this->seeStatusCode( 200 );
    }

Controller:

    public function test(Request $request)
    {
        $token = $request->bearerToken();
        $userid = $request->user();

        if ($token != $userid)
           abort(400, 'UserId mismatch');
    }

AuthServiceProvider:

    public function boot()
    {
        $this->app['auth']->viaRequest('api', function ($request) {
            return $request->bearerToken();
        });
    }

When logging the results in the Controller:
1st request: Bearer Token 'User1'. UserId 'User1'
2nd request: Bearer Token 'User2'. UserId 'User1'

Tested on Lumen 5.2 and 5.4

All 5 comments

I am fairly sure you can only make one $request to your application per test, unless you manually refresh the application between calls.

Would be better to separate each request into its own test.

See something like https://github.com/laravel/framework/issues/9369

Having separate tests adds unnecessary complexity - the developer then needs to deal with sequencing the tests and passing data between the tests.

Consider typical API test cases:

  • (1) add item, then (2) retrieve list of items and check the item was added.
  • (1) add items, (2) check that item was added, (3) remove item, (4) check that item was removed.

Actually - that should all be separate tests anyway:

(1) add item,

  1. Add item
  2. Check database

(2) retrieve list of items

  1. Get list of items
  2. Check against database

(3) remove item,

  1. Remove item
  2. Check database

Anyway - I think this is better for the forums. Or a discussion on laravel/internals if you think the behavior should be changed.

It's best to split this up into separate tests like @laurencei suggested.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

maglor picture maglor  路  3Comments

dunice picture dunice  路  3Comments

GGNB picture GGNB  路  5Comments

jairobjunior picture jairobjunior  路  4Comments

cvinothkumar picture cvinothkumar  路  3Comments