Laravel 5.1 PHPUnit with "use DatabaseMigrations;" Produces Error when Accessing Test DB

757 views Asked by At

I'm just learning PHPUnit with Laravel 5.1. I'm using "use DatabaseMigrations" to migrate the test database for each test, which I set in my phpunit.xml:

<php>
    ...
    <env name="DB_DATABASE" value="project_test"/>
    ...
</php>

I've setup a bunch of basic tests as I go along to check instantiation, factories, etc, but I wanted to check an accessor and a mutator I have in the UserModel:

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

public function getPasswordAttribute($password)
{
    $this->attributes[ 'password' ] = bcrypt($password);
}

But when the accessor test runs:

/**
 * A basic check of full name accessor.
 *
 * @return void
 */
public function testCheckFullNameOfUser()
{
    $user = User::all();

    $this->assertEquals($user->first_name . ' ' . $user->last_name, $user->fullname);
}

I get this error:

1) UserTest::testCheckFullNameOfUser
ErrorException: Trying to get property of non-object

Which seems to suggest that the database hasn't been migrated, and SSHing into Homestead and logging into MySQL and checking the migrations table the test database is empty with no migrations appearing to have occurred.

What have I missed in the documentation to make this work? I can make it pass by just reusing the user factory, but I don't understand why I can't access the test database, does it need to be initially migrated?

1

There are 1 answers

1
BrokenBinary On BEST ANSWER

You are getting that error because you don't have any users in your database.

First, when you use DatabaseMigrations in your tests Laravel goes ahead and runs your migrations before every single test and performs a "rollback" after every single test. That way you have a fresh database for every test and leftover data from one test won't affect subsequent tests.

This means that if one of your tests expects there to be users in the database, then you need to create them in that test. This also explains why there wasn't any data in your test database when you looked.

Second, User::all() returns a collection of users. If you want a single user you should try User::first().

Try this test:

public function testCheckFullNameOfUser()
{
    User::create(['first_name'=>'John', 'last_name'=>'Smith']);
    $user = User::first();

    $this->assertEquals('John Smith', $user->fullname);
}