Laravel 5.1 Unable to Run Test on User Password Mutator

1.5k views Asked by At

I have a password mutator:

/**
 * Mutator for setting the encryption on the user password.
 *
 * @param $password
 */
public function getPasswordAttribute($password)
{
    $this->attributes[ 'password' ] = bcrypt($password);
}

That I'm trying to test:

/**
 * A basic check of password mutator.
 *
 * @return void
 */
public function testCheckPasswordEncryptionUserAttribute()
{
    $userFactory = factory('Project\User')->create([
        'password' => 'test'
    ]);

    $user = User::first();

    $this->assertEquals(bcrypt('test'), $user->password);
}

That when the test runs I get this error:

1) UserTest::testCheckPasswordEncryptionUserAttribute
Failed asserting that null matches expected '$2y$10$iS278efxpv3Pi6rfu4/1eOoVkn4EYN1mFF98scSf2m2WUhrH2kVW6'.

After the test failed I attempted to dd() the password property, but that also failed. My first thought was this might be a mass assignment issue (having just read about that), but password is in $fillable (which makes sense that it would be there), then I noticed $hidden in the User class as well, but after reading about that in the docs, and also removing the password index for $hidden it still produces a null when you try to access the password property.

How would you unit test this mutator, or what have I missed?

1

There are 1 answers

3
Armen Markossyan On BEST ANSWER

You just have to change "get" to "set" in your method name.

Methods starting with "get" are accessors. These are not supposed to change the field / attribute value but return a "mutated" value (yours returns nothing that's why you get null).

Methods starting with "set" are designed to change the value of the field (mutators) and this seems to be exactly what you need.

http://laravel.com/docs/5.0/eloquent#accessors-and-mutators

/**
 * Mutator for setting the encryption on the user password.
 *
 * @param $password
 */
public function setPasswordAttribute($password)
{
    $this->attributes['password'] = bcrypt($password);
}

You can make "password" hidden, because this won't affect your test.

P.S. If I'm not wrong, factory('...')->create() returns an instance of a newly created model (\Illuminate\Database\Eloquent\Model), so you don't have to do User::first():

/**
 * A basic check of password mutator.
 *
 * @return void
 */
public function testCheckPasswordEncryptionUserAttribute()
{
    $user = factory('Project\User')->create(['password' => 'test']);

    $this->assertTrue(Hash::check('test', $user->password));
}