0

I created a Laravel test class with PHPUnit which has two methods as below,

class MainLocationTest extends TestCase
{
    use RefreshDatabase, TestUserTrait;

    public static function getMainLocationCount(): int
    {
        return InventoryLocation::whereActive(1)->count();
    }

    /**
     * Test main location creation
     */
    public function testCreateMainLocation(): void
    {
        self::setActingAdminUser();

        $this->assertEquals(0, self::getMainLocationCount());

        $response = $this->postJson('/api/inventory/location/main/create', [
            'location_name' => 'Test Main Location',
            'location_address' => '',
            'location_code' => '',
            'location_manager_id' => '',
        ]);

        $response->assertStatus(200);
        $this->assertEquals(1, self::getMainLocationCount());
    }

    /**
     * Test main location update
     */
    public function testUpdateMainLocation(): void
    {
        self::setActingAdminUser();
        
        $main_location = InventoryLocation::whereActive(1)->first();
        $this->assertEquals('Test Main Location', $main_location->location_name);

        $response = $this->postJson("/api/inventory/location/main/$main_location->id/edit", [
            'location_name' => 'Test Main Location Updated',
            'location_address' => '',
            'location_code' => '',
            'location_manager_id' => '',
        ]);

        $response->assertStatus(200);

        $main_location = InventoryLocation::find($main_location->id);
        $this->assertEquals('Test Main Location Updated', $main_location->location_name);
    }
}

My PHPUnit settings are,

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
         bootstrap="vendor/autoload.php"
         colors="true"
>
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
        <testsuite name="Modules">
            <directory suffix="Test.php">./Modules/*/Tests/Feature</directory>
            <directory suffix="Test.php">./Modules/*/Tests/Unit</directory>
        </testsuite>
    </testsuites>
    <coverage processUncoveredFiles="true">
        <include>
            <directory suffix=".php">./app</directory>
        </include>
    </coverage>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="BCRYPT_ROUNDS" value="4"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="DB_CONNECTION" value="sqlite"/>
        <env name="DB_DATABASE" value=":memory:"/>
        <env name="MAIL_MAILER" value="array"/>
        <env name="QUEUE_CONNECTION" value="sync"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="TELESCOPE_ENABLED" value="false"/>
    </php>
</phpunit>

When I run the test cases, testCreateMainLocation test get passed and testUpdateMainLocation test throw an error saying Attempt to read property "location_name" on null. But, when two methods are merged into one and run, all tests get passed.

It seems database is getting deleted when coming to testUpdateMainLocation test. So, I cannot get the location which was created in the testCreateMainLocation test. Is there a way to avoid database refresh till the end of execution of the class?

(I tried removing RefreshDatabase trait. But, it was not successfull)

  • You are using `RefreshDatabase` trait, that will literally clean the database (truncate all tables) and have the clear before the test starts. If you are seeding the database, you should be using `DatabaseTransaction`, or use the `setUp` method from PHPUnit and create a new model there. – matiaslauriti Oct 03 '22 at 18:26

0 Answers0