joaoVtr's avatar

ModelTestCase test Scout Searchable trait error

Laravel 9

Hi, I have a trouble when i try to test my model using unit test. To be especific, only the Searchable trait is breaking my my tests.

I'm using the ModelTestCase: class UserModel extends ModelTestCase

and in my traits test i have something like:

protected function traits(): array{
    return [
        HasFactory::class,
        SoftDeletes::class,
        LogsActivity::class,
        Searchable::class,
    ];
}

and i have that error when i run php artisan test

• App\Models\Common\UserTest> traits RuntimeException

A facade root has not been set.

at vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:335

331▕     {
332▕         $instance = static::getFacadeRoot();
333▕
334▕         if (! $instance) {

➜ 335▕ throw new RuntimeException('A facade root has not been set.'); 336▕ } 337▕ 338▕ return $instance->$method(...$args); 339▕ }

3 [internal]:0 App\Models\Common\User::bootSearchable()

8 tests/Unit/App/Models/Common/UserTest.php:29 Illuminate\Database\Eloquent\Model::__construct()

I think the bootSearchable function in Searchable trait causes the problem, more especifically that line static::observe(new ModelObserver);, but i don't know how to fix it. Any idea? Thanks for the help in advance.

0 likes
6 replies
joaoVtr's avatar

@Sinnbeck Hi, thank for the replic. It is something gereric like that:

class UserTest extends ModelTestCase {

protected function model(): Model
{
    return new User();
}

protected function traits(): array
{

    return [
        HasFactory::class,
        SoftDeletes::class,
        LogsActivity::class,
        Searchable::class,
    ];
}

protected function fillable(): array
{
    return [
        'name',
        'email', 
    ];
}

protected function casts(): array
{
    return [
        'id' => 'int',
        'deleted_at' => 'datetime',
    ];
}

}

The ModelTestCase:

namespace Tests\Unit\App\Models;

use Illuminate\Database\Eloquent\Model;

use PHPUnit\Framework\TestCase;

abstract class ModelTestCase extends TestCase { abstract protected function model(): Model;

abstract protected function traits(): array;

abstract protected function fillable(): array;

abstract protected function casts(): array;

public function test_traits()
{
    $traits = array_keys(class_uses($this->model()));

    $this->assertEquals($this->traits(), $traits);
}

public function test_fillable()
{
    $fillable = $this->model()->getFillable();

    $this->assertEquals($this->fillable(), $fillable);
}


public function test_has_casts()
{
    $casts = $this->model()->getCasts();

    $this->assertEquals($this->casts(), $casts);
}

}

And in my model

use Laravel\Scout\Searchable

class User extends Model implements Explored { use HasFactory, SoftDeletes, LogsActivity, Searchable; }

Every tests works fine, but when i have implemented the laravel scout trait on test(searchable. And laravel scout works very fine when i test manualy) that error is inputed on test.

I'm sorry about the code desgin, it's my very first post on laracast. Thank for your time.

Sinnbeck's avatar

@joaoVtr so exactly that problem I described. You don't use create application (extend laravels test case)

1 like
joaoVtr's avatar

@Sinnbeck You were right. I have tried to use the CreatesApplication trait without use the laravel test class, cause i was using the phpunit test class. My bad. Thanks for the answer.

tykus's avatar
tykus
Best Answer
Level 104

@joaovtr what is this test actually proving - it is nothing more than a box-ticking exercise.

Aside, the problem is use PHPUnit\Framework\TestCase; where you need to extend the Tests\TestCase abstract class, because PHP doesn't know to bootSearchable but Laravel does.

1 like
joaoVtr's avatar

@tykus It Works very well

namespace Tests\Unit\App\Models;

use Illuminate\Database\Eloquent\Model;

// That line makes the diference

use Tests\TestCase;

abstract class ModelTestCase extends TestCase

Thanks so much for the help.

Now i have another problem with elasticsearch on github actions, but i need to try somes stuffs

1 like

Please or to participate in this conversation.