skip to Main Content

I just created a factory in order to run some tests:

CategoryFactory.php

<?php

namespace DatabaseFactories;

use IlluminateDatabaseEloquentFactoriesFactory;

/**
 * @extends IlluminateDatabaseEloquentFactoriesFactory<AppModelsCategory>
 */
class CategoryFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            //
            'company_id' => 1,
            'name' => fake()->name(),
            'parent_id' => null
        ];
    }
}

And added it to the model:

Category.php

<?php

namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentSoftDeletes;

use AppScopesCompanyScope;

class Category extends Model
{
    //
    use SoftDeletes, HasFactory;

    protected $fillable = [
        'company_id',
        'name',
        'parent_id'
    ];

public function __construct() {
    parent::__construct();
    if(isset(auth()->user()->company_id)) {
        $this->attributes['company_id'] = auth()->user()->company_id;
    }
}


protected static function boot()
{
    parent::boot();

    static::addGlobalScope(new CompanyScope);
}

My test file looks like this:

public function test_category_edit_can_be_redered(): void
    {
        $user = User::factory()->create();
        $category = Category::factory()->create();

        $response = $this->actingAs($user)->get('/devices/categories/1/edit');

        $response->assertStatus(200);
    }

But when I try to run the test, I get the following error:

General error: 1364 Field 'company_id' doesn't have a default value (Connection: mysql, SQL: insert into `categories` (`updated_at`, `created_at`) values (2023-08-08 01:55:43, 2023-08-08 01:55:43))

It looks like the definition in the factory is not being applied to the create method… Any idea what I am doing wrong?

2

Answers


  1. Chosen as BEST ANSWER

    If anyone face this issue in the future, here is the answer:

    Laravel factory fails when the model has a constructor


  2. You trigger your category before you signIn a user so that the code doesn’t have a default auth()->user()

    Your code trigger a global scope event which is overriding the default company_id

    you can use use IlluminateDatabaseConsoleSeedsWithoutModelEvents or saveQuietly() in your seeder to not trigger global scope events.

    You can also do this I think:

    public function test_category_edit_can_be_redered(): void
        {
            $user = User::factory()->create();
            Auth::loginUsingId($user->id);
            $category = Category::factory()->create();
    
            $response = $this->actingAs($user)->get('/devices/categories/1/edit');
    
            $response->assertStatus(200);
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search