Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock Laravel's eloquent accessor attribute

I'm implementing unit tests into my Laravel 4 application but I'm stuck on mocking accessor attributes.

I have an Eloquent model that has an Accessor attribute in it. I'm trying to mock this model and return a value when this accessor attribute is called. But I can't find any solution for it to make it work.

My super simple user class.

class User extends Eloquent {
    public function getFullNameAttribute() {
        return $this->first_name . ' ' . $this->last_name;
    }
}

I tried the following:

$user_mock = m::mock('MyApp\Models\User');

$user_mock->shouldReceive('__get')->with('full_name')->andReturn('John Snow'); // doesn't work
$user_mock->shouldReceive('getAttribute')->with('full_name')->andReturn('John Snow'); // doesn't work
$user_mock->shouldReceive('getFullNameAttribute')->andReturn('John Snow'); // doesn't work

echo $user_mock->full_name; // --> " "

I just get an empty space back, indicating that the original function is still being called.

like image 725
Sven van Zoelen Avatar asked Jun 05 '15 10:06

Sven van Zoelen


1 Answers

Try not to mock eloquent models. This is an example of "mocking a type you don't own". If Laravel changes the eloquent internals in a new release, and you have mocked them in your unit tests, then your tests may provide false positives.

In addition I think it's odd to try and mock them. You lose the idea that these entities map to real world things, while it is the business logic components that need to be tested in isolation (with dependencies mocked).

When using accessors I have found it helpful to wrap it in another abstraction, for instance in a Repository layer:

public function getFirstNameAttribute()
{
     return app(UserRepository::class)->getFirstName($this);
}

I find accessors make the client code extremely readable. This is fully testable and the entire interaction with the database is mockable, which might be useful in reducing overhead if you have thousands of tests.

like image 166
jwj Avatar answered Nov 05 '22 18:11

jwj