Home > Back-end >  Why making tests passed parameter into method is empty?
Why making tests passed parameter into method is empty?

Time:07-11

Making http test in laravel 8 in control I create $itemObject object with factory and pass it for edit method

use Tests\TestCase;

class ControllersItemObjectController extends TestCase
{
    use DatabaseMigrations;

    /** @test */
    public function edit_item_object()
    {
        $this->withoutMiddleware();
        $itemObject = ItemObject::factory()->create();

        \Log::info(json_encode($itemObject);  // I see valid object logged
        \Log::info(gettype($itemObject)); // it shows "object"

        $this->asAdmin()->get(route('item-objects.edit', ['item_object' => $itemObject]));

and I got error :

 Missing required parameter for [Route: item-objects.update] [URI: item-objects/{item_object}] [Missing parameter: item_object]. (View:
 /resources/views/item-objects/edit.blade.php)

in routes I have :

|        | GET|HEAD  | item-objects/{item_object}/edit             | item-objects.edit               | App\Http\Controllers\ItemObjectController@edit                        | web                                          |

But in ItemObjectController controller I have :

 public function edit(ItemObject $itemObject)
    {
        \Log::info(  json_encode($itemObject) );   // but it returns empty array
        return view('item-objects.edit', [
            ...
        ]);
    }

As parameter $itemObject above is empty it raise error in /resources/views/item-objects/edit.blade.php template above. But I do not see why this parameter is empty ? Where I lose this value passing valid object into ItemObjectController.edit method?

If there is a way to debug it ? I can not use TELESCOPE for tests...

In route parameter is "item_object", but var name is "$itemObject" I do not see wht $itemObject is empty ...

Thanks in advance!

CodePudding user response:

First of all, the error is being shown for item-objects.update, but the route you have shared is for item-objects.edit.

So, you have also shared the controller for edit, and you are using item_object in the route but using $itemObject in your controller... When you want to use Implicit Model Binding you have to match the parameter with the variable name, so you either use itemObject or item_object (I would recommend the first one):

public function edit(ItemObject $itemObject)
{
    return view('item-objects.edit', [
        ...
    ]);
}
Route::get(`item-objects/{itemObject}/edit`, [\App\Http\Controllers\ItemObjectController::class, 'edit'])
    ->name('item-objects.edit);

After that is done, your test should also match the route:

public function edit_item_object()
{
    $this->withoutMiddleware();

    $itemObject = ItemObject::factory()->create();

    $this->asAdmin()
        ->get(route('item-objects.edit', ['item_object' => $itemObject]));

CodePudding user response:

In this case you dont need to encode to json. You need to pass the attribute which is used for model bindings in your routes file.

as an example, you can have something like this:

Route::bind('item_object', fn (string $value) => ItemObject::query()->findOrFail($value));

The code above, responsible for mapping route param with model from DB. But in your case it might be different. I do prefer to follow explicit model bindings,instead of magic :)

https://laravel.com/docs/9.x/routing#route-model-binding

  • Related