Mustafa Khaled
Mustafa Khaled

Reputation: 153

Laravel - phpunit fails the UPDATE method i dont know why

it's my first time writing test so I wrote one for the update method and I don't know what I did wrong and if there's a better way of doing the test inform me please, thanks in advance

Routes

Route::group(['prefix' => 'categories' , 'namespace' => 'App\Http\Controllers\Admin'] , function () {
    Route::post('create', 'CategoryController@store')->name('category.store');
    Route::put('update/{category}', 'CategoryController@update')->name('category.update');
});

Here's my Controller

Controller

public function update(Request $request , Category $category)
{
    $category->update($request->all());
}

Test

/** @test */
public function a_category_can_be_updated()
{
    $this->withoutExceptionHandling();
    $this->post(
        route('category.store'),
        [
            'name' => 'Food',
            'slug' => 'food-and-drinks',
        ],
    );

    $category = Category::first();
    $this->put(
        route('category.update', $category->id),
        [
            'name' => 'Food and',
        ],
    );
    // dd($category);

    $this->assertEquals('Food and', $category->name);
    $this->assertEquals('Food-and', $category->slug);
}

the Error comes from the Test

  • Tests\Feature\CategoriesTest > a category can be updated
  Failed asserting that two strings are equal.

  at F:\newProject\tests\Feature\CategoriesTest.php:66
     62▕             ],
     63▕         );
     64▕         // dd($category);
     65▕
  ➜  66▕         $this->assertEquals('Food and', $category->name);
     67▕         $this->assertEquals('Food-and', $category->slug);
     68▕     }
     69▕ }
     70▕

  1   F:\newProject\vendor\phpunit\phpunit\phpunit:61
      PHPUnit\TextUI\Command::main()
  --- Expected
  +++ Actual
  @@ @@
  -'Food and'
  +'Food'

Model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;

class Category extends Model
{

    protected $table = 'categories';
    public $timestamps = true;

    use SoftDeletes;

    protected $dates = ['deleted_at'];
    protected $fillable = array('name', 'slug', 'parent_id');

    public function posts()
    {
        return $this->belongsToMany('App\Models\Post');
    }


    //slugging the Category-name
    public function setSlugAttribute($value)
    {
        $this->attributes['slug'] = Str::slug($this->attributes['name']);
    }

    public function scopeParent()
    {
         return Category::whereNull('parent_id');
    }

}

let me know what is going on with the code, thanks in advance

Upvotes: 2

Views: 2250

Answers (3)

I Want Answers
I Want Answers

Reputation: 441

I know this is not directly related to your question but I'm posting this for visibility in case someone else like me comes here, facing same challenge

It turned out to be caused by my enum column on that table. In the migration, the values were filled with integers coming from class constants on the model.

class Project extends Model
{
    use HasFactory;

    public const TABLE_NAME = "projects", STATUS_SOLD = 4,

    STATUS_AVAILABLE = 1, STATUS_ONGOING = 2,

    STATUS_CANCELLED = 5, STATUS_ONHOLD = 3

I tried to update that column using same constants and the method was returning true despite silently failing

$project->update([ // this returns true and even the model shows the new value. But running refresh/fresh/find reverts to old value cuz operation failed

                "status" => Project::STATUS_AVAILABLE
            ]);

So I wrapped the consts in strval and the update operation was being performed successfully

project->update([

                "status" => strval(Project::STATUS_AVAILABLE)
            ]);

Upvotes: 0

Atef Ghribi
Atef Ghribi

Reputation: 56

As stated by "IGP" you have to use $category->fresh() after performing the update. But assign that to your$category as follows: $category = $category->fresh();

Check the Laravel Documentation for details: Eloquent ORM Refreshing Models

Upvotes: 3

IGP
IGP

Reputation: 15909

When doing this request,

$this->put(
    route('category.update', $category->id),
    [
        'name' => 'Food and',
    ],
);

you're only updating the Category's name with this request so after this, $category->slug will still be equal to food.

Nothing in your Model suggests the slug will be automatically updated.

Also, since the update was not done through the $category variable, you need to refresh its data after the put request with $category->fresh();

Upvotes: 2

Related Questions