Laravel Testing: HasMany BelongsTo

Laravel Testing: HasMany BelongsTo

Laravel Testing relationships HasMany BelongsTo in a feature test

A famous tasklist where we need to test that we can access a task owner, or the user have tasks.

It can be anything else, a user have articles, comments, orders or anything else. User hasMany relationship, and its reverse, a task BelongsTo user.

If we follow test driven developement we need to setup our tests first. however to save some of your time I will try to be as quick as possible, this just give you ideas how this can be tested, you might use this however you wish to test other relationships.

Lets start from a brand new Laravel 8 installation. we. add new test. a feature test, while it is kinda a unit test, this is not behaviour of our application. It does requires the entire Laravel application, to run migration, and get the relationship working.

php artisan make:test UserTaskRelationshipTest
// or 
php artisan make:test Http/Controllers/TasksControllerTest

Setting up our test a task belongs to a user.

/** @test */
public function tasks_has_owner_relationship(): void
{
    $user = User::factory()->create();
    $task = Task::factory(['user_id' => $user->id])
    ->create();

        // returns a user instance
    $this->assertInstanceOf(User::class, $task->owner);
        // returns a relationship instance
    $this->assertInstanceOf(BelongsTo::class, $task->owner());
        // fresh is to pull in user from database
    $this->assertEquals($user->fresh(), $task->owner);
}

We need to generate Task model, migration, factory, and then add the relationship owner() to tasks.

php artisan make:model Task -m -f
//Task model
use HasFactory;

public function owner(): object
{
    return $this->belongsTo(User::class, 'user_id');
}
// CreateTasksTable migration
$table->id();
$table->unsignedInteger('user_id');
return [
    'user_id' => User::factory()->create()->id,
    ];

A user has many tasks

/** @test */
public function user_hasMany_tasks(): void
{
    $user = User::factory()
        ->hasTasks(3)
        ->create();

    $allTasks = Task::all();
    $this->assertEquals($user->tasks, $allTasks);

    $this->assertInstanceOf(Task::class, $user->tasks->first());
    $this->assertInstanceOf(Task::class, $user->tasks()->first());
    $this->assertInstanceOf(Collection::class, $user->tasks);
    $this->assertInstanceOf(HasMany::class, $user->tasks());
}
public function tasks(): object
{
    return $this->hasMany(Task::class, 'user_id');
}

Happy testing!