morteza's avatar
Level 12

How to unit test eloquent scopes?

I want to unit test to see if specific scope will be called if i call repository method but i don't know how can i do this. Let say i have a Mobile model:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Mobile extends Model
{
    protected $casts = [
        'verified_at' => 'datetime',
    ];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function scopeNumberIs($query, $number)
    {
        return $query->where('number', $number);
    }
}

And i have a MobileRepository for it:

namespace App\Repositories;

use App\Contracts\MobileInterface;
use App\Contracts\UserInterface;
use App\Mobile;
use App\User;

class MobileRepository extends Repository implements MobileInterface
{
    public function __construct(Mobile $mobileModel)
    {
        parent::__construct($mobileModel);
    }

    public function getRelatedUserByNumber(string $number): UserInterface
    {
        $user = optional($this->model->numberIs($number)->first())->user;

        if (is_null($user)) {
            $user = new User;
        }

        return new UserRepository($user);
    }
}

Now i want to make a test to see is scopeNumberIs will be fired when i call getRelatedUserByNumber. I mocked Mobile model but it's calling some other methods that i don't know how to handle them! should i mock them too or there is an easier way. How you do this?

0 likes
4 replies
D9705996's avatar

Don't test scopeNumberIsdirectly as your then essentially texting eloquent.

Test that you get the correct output given a set input.

E.g. if you call getRelatedUserByNumber(1)assert that the user in your UserRepository has a number 1

If you remove your ->numberIs($number) prior to running the test it should fail. Readd it and it should pass which confirms your scope is working.

morteza's avatar
Level 12

Thank you @D9705996 . I see you are telling me it should be on integration test not in unit test, am i right? I want to see if there is a way to unit test my repository function. I just want to know if eloquent calls the scope.

D9705996's avatar

@morteza - to be honest I don't give to much time what is an integration and what is a unit test. I just care that my code does what it should. Technically an integration test and if you want a unit test to test this function in isolation your going to have mock out all your other dependencies. It's a lot of work for zero benefit IMHO

1 like
Sergiu17's avatar
// unit test
$this->assertInstanceOf(Builder::class, Mobile::numberIs(1));

This is unit test

5 likes

Please or to participate in this conversation.