CLab's avatar
Level 3

Laravel 8 create user to be used for entire test class

I have a laravel 8 project. I want to create a new user using factory with specific role e.g. admin, to be used for the entire class of tests. I am trying to do this using setUpBeforeClass().

Here is what I have so far:

PostPagesTest.php

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

use App\Models\User;

class PostPagesTest extends TestCase
{

    protected $adminUser;

    public static function setUpBeforeClass(): void
    {
        parent::setUpBeforeClass();
        self::$adminUser = User::factory()->withRole('admin')->create();  // works under tinker
    }

    public function test_index_page_visible_as_admin()
    {
        $response = $this->actingAs($this->adminUser)
            ->get('/posts')
            ->assertSeeText('Posts')
            ->assertStatus(200);
    }

    public function test_create_page_visible_as_admin()
    {
        $response = $this->actingAs($this->adminUser)
            ->get('/posts/create')
            ->assertStatus(200);
    }
}

Unfortunately, when I run the test using php artisan test --filter=PostPagesTest I get the following error:

  Call to a member function connection() on null

  at C:\project\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php:1653
    1649▕      * @return \Illuminate\Database\Connection
    1650▕      */
    1651▕     public static function resolveConnection($connection = null)
    1652▕     {
  ➜ 1653▕         return static::$resolver->connection($connection);
    1654▕     }
    1655▕
    1656▕     /**
    1657▕      * Get the connection resolver instance.

Any ideas on how I can do this i.e. create an admin user and use it through my tests.

0 likes
8 replies
Nakov's avatar

and have you tried by calling the parent class method before?

 public static function setUpBeforeClass(): void
{
    parent::setUpBeforeClass();
    self::$adminUser = User::factory()->withRole('admin')->create(); 
}
Nakov's avatar

@CLab based on your test functions above, I would use the setUp method instead, and even though the user might be new each time, it will be an admin. IMO the test methods should not share state if that's what you are after. If it is just the user, then a simple setUp method will do it. Also make sure that you use any of the traits to refresh the database after each run.

public $adminUser;

public function setUp(): void
{
    parent::setUp();
    $this->adminUser = User::factory()->withRole('admin')->create(); 
}
CLab's avatar
Level 3

@Nakov The problem with this is too many users being created and deleted. I have like >50 tests and 5 roles against which to test them. So it becomes quite inefficient.

CLab's avatar
Level 3

@Nakov I thought that PHPUnit would use the environment settings. I need to use Postgres and would prefer to use a local DB (which is a clone of my production) as the test DB. Please provide advise on how I can use it.

Cassio's avatar

Hi,

Is your phpunit.xml with the right connection to the database?

CLab's avatar
Level 3

@Cassio I am assuming it is, as everything else works e.g. in tinker the command to create the User in the database works. It also works to create the user within the individual tests.

Please or to participate in this conversation.