Pest: Call to a member function connection() on null

Created on 7 Jun 2020  路  13Comments  路  Source: pestphp/pest

Hi Guys, I have the following error using Pest on a fresh installation of Laravel & Nova:

Call to a member function connection() on null at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1342

I'm trying to test a custom validation rule which uses the database.

Directory structure:

app/
domains/
    Systeem/
        Rules/
            User/
                MinimaalEenAdmin.php
        tests/
            Unit/
                Rules/
                    User/
                        MinimaalEenAdminTest.php

My Test:

<?php

use Domains\Systeem\Rules\User\MinimaalEenAdmin;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('een gebruiker beheerder maken kan altijd', function () {
    $rule = new MinimaalEenAdmin();

    assertTrue($rule->passes('admin', true));
});

test('een gebruiker geen beheerder maken zonder beheerders kan niet', function () {
    $rule = new MinimaalEenAdmin();

    assertFalse($rule->passes('admin', false));
});

My custom validation rule:

<?php

namespace Domains\Systeem\Rules\User;

use Domains\Systeem\User;
use Illuminate\Contracts\Validation\Rule;

class MinimaalEenAdmin implements Rule
{
    private $resourceId;

    public function __construct($resourceId = null)
    {
        $this->resourceId = $resourceId;
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param string $attribute
     * @param mixed $value
     *
     * @return bool
     */
    public function passes($attribute, $value): bool
    {
        if ($value === '1') {
            return true;
        }

        return User::query()
            ->where('admin', '=', true)
            ->when($this->resourceId, static function ($query, $resourceId) {
                $query->where('id', '!=', $resourceId);
            })
            ->exists();
    }

    public function message(): string
    {
        return __('systeem::validation.minimaal-een-admin');
    }
}

composer.json:

"require": {
        "php": "^7.4.1",
        "fideloper/proxy": "^4.3.0",
        "fruitcake/laravel-cors": "^1.0.6",
        "guzzlehttp/guzzle": "^6.5.4",
        "laravel/framework": "^7.14.1",
        "laravel/nova": "^3.6.0",
        "laravel/tinker": "^2.4.0"
    },
    "require-dev": {
        "facade/ignition": "^2.0.6",
        "fzaninotto/faker": "^1.9.1",
        "mockery/mockery": "^1.4.0",
        "nunomaduro/collision": "^5.0",
        "pestphp/pest": "^0.1.5",
        "phpunit/phpunit": "^9.2.1"
    },
    "config": {
        "optimize-autoloader": true,
        "preferred-install": "dist",
        "sort-packages": true
    },

My phpunix.xml

<?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>
            <directory suffix="Test.php">./domains/Systeem/tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
            <directory suffix="Test.php">./domains/Systeem/tests/Feature</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
            <directory suffix=".php">./domains</directory>
        </whitelist>
    </filter>
    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <server name="DB_CONNECTION" value="sqlite"/>
        <server name="DB_DATABASE" value=":memory:"/>
        <server name="MAIL_MAILER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <server name="TELESCOPE_ENABLED" value="false"/>
    </php>
</phpunit>

This test works fine:

<?php

use Domains\Systeem\Rules\User\MinimaalEenAdmin;
use Domains\Systeem\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

class MinimaalEenAdminTest extends \Tests\TestCase
{
    use RefreshDatabase;

    /** @test */
    function een_gebruiker_beheerder_maken_kan_altijd()
    {
        $rule = new MinimaalEenAdmin();

        $this->assertTrue($rule->passes('admin', '1'));
    }

    /** @test */
    function een_gebruiker_geen_beheerder_maken_zonder_beheerders_kan_niet()
    {
        $rule = new MinimaalEenAdmin();

        $this->assertFalse($rule->passes('admin', false));
    }
}

Most helpful comment

Thanks, this fixed the problem:

<filter>
    <whitelist processUncoveredFilesFromWhitelist="true">
        <directory suffix=".php">./app</directory>
        <directory suffix=".php">./domains</directory>
        <exclude>
            <directory>./domains/*/database</directory>
        </exclude>
    </whitelist>
</filter>

All 13 comments

Can I see your Pest.php file?

Hi @nunomaduro,

Here it is:

<?php

uses(Tests\TestCase::class)->in('Feature');

Also tried removing ->in('Feature'); but that didn't work either.

The funny thing is when I place de pest tests under the normal phpunit tests I get a different error:

Unable to locate factory for [Domains\Systeem\User].
or
Target class [config] does not exist.

When I remove the phpunit tests I got the connection error back. It looks like Laravel is not booted properly or something.

Running only the phpunit style tests works with ./vendor/bin/pest but when I add --coverage the following error is given: Undefined variable: factory at domains/Systeem/database/factories/UserFactory.php:20

Using uses(Tests\TestCase::class)->in('Feature', 'Unit'); will fixed your problem.

@nunomaduro the Call to a member function connection on null is gone but now I got 2 new errors:

Illuminate\Contracts\Container\BindingResolutionException 

Target class [config] does not exist.

at vendor/laravel/framework/src/Illuminate/Container/Container.php:807

and

Unable to locate factory for [Domains\Systeem\User].

at vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:273

The --coverage still gives the Undefined variable: factory at domains/Systeem/database/factories/UserFactory.php:20 even with the uses(Tests\TestCase::class)->in('Feature', 'Unit');

Using ./vender/bin/phpunit works fine.

@cliffordjames All the folders that use Laravel someway need to be listed on the in method: uses(Tests\TestCase::class)->in('Feature', 'Unit');

@nunomaduro Thanks, that works:

<?php

uses(Tests\TestCase::class)->in(
    'Feature',
    'Unit',
    '../domains/Systeem/tests/Unit',
);

The only problem that still exists is the one with --coverage

./vendor/bin/pest --coverage

Whoops\Exception\ErrorException 

Undefined variable: factory

at domains/Systeem/database/factories/UserFactory.php:20

Does your factory file have a PHPDoc tag at the top like this?

/** @var \Illuminate\Database\Eloquent\Factory $factory */

It might just be because it can't work out where the $factory instance is coming from when doing the coverage.

@owenvoke yes the factory file starts with:

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */
...

Ah, ok. That's interesting that it's failing to find the variable. 馃え

@cliffordjames

    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
            <directory suffix=".php">./domains</directory>
        </whitelist>

The user factories/UserFactory.php file can not be processed by coverage.

Thanks, this fixed the problem:

<filter>
    <whitelist processUncoveredFilesFromWhitelist="true">
        <directory suffix=".php">./app</directory>
        <directory suffix=".php">./domains</directory>
        <exclude>
            <directory>./domains/*/database</directory>
        </exclude>
    </whitelist>
</filter>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

JacobBennett picture JacobBennett  路  6Comments

faustbrian picture faustbrian  路  5Comments

dingo-d picture dingo-d  路  6Comments

reed-jones picture reed-jones  路  6Comments

rihardssceredins picture rihardssceredins  路  5Comments