0

I'm new to Laravel and am following along with the Play by Play: Getting Started with Laravel 5 with Steven Maguire video in Pluralsight. This is a clean install of the lavarvel/laravel box in Vagrant. Laravel is at version 5.4.15 and PHPUnit is at version 5.7.16.

However, I can't seem to get my route tests to not fail as I add groups and controllers.

Here's my routes/web.php file:

<?php
Route::get('products', ['as' => 'products', function(){
    return App\Product::all();
}]);

Here's my tests/Unit/ExampleTest.php:

<?php

namespace Tests\Unit;

use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Http\Response;

class ExampleTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        $this->assertTrue(true);
    }
    public function testProductsList(){
        $this->get(route('products'))
            ->assertResponseOk();
    }
}

With just this basic setup, when I run my tests, I get this response: Error: Call to undefined method Illuminate\Http\Response::assertResponseOk()

After reading around, I restructured the test to this:

public function testProductsList(){
    $response = $this->get(route('products'));
    $this->assertEquals(200, $response->status());
}

This new structure succeeds, so I proceeded with the video and next we added a route group. Here's the route group in the routes\web.php file:

Route::group(['prefix' => 'api'], function(){
    Route::get('products', ['as' => 'products', function(){
        return App\Product::all();
    }]);
});

This also succeeds. The problems begin when I introduce Route::resource into the flow. The tests begin to fail. Here's the new routes\web.php file:

Route::group(['prefix' => 'api'], function(){
    Route::resource('products', 'ProductController', ['only' => ['index', 'store', 'update']]);
});

Here's the ProductController class in this file app/Http/Controllers/ProductController.php:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ProductController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }
}

I used php artisan make:controller ProductController to create this controller. Here's the error that I now receive: InvalidArgumentException: Route [products] not defined.

I tried to change the adjusted testProductsList() method back to the original code and it still doesn't work.

Any insights into how I can get past these errors? I'd prefer to keep the original testProductsList() method code, however, if that's just not how it works anymore, then as long as I can get it working, I'm fine. Thanks in advance for your help and insight!

EDIT

Per the comment, I deleted and recreated the ProductController class using the command php artisan make:controller ProductController --resource. I've edited the above contents in the file app/Http/Controllers/ProductController.php to reflect the change. However, the test is still failing. With Alex's answer, I've also changed the testProductsList method to this, but with no change:

public function testProductsList(){
    /*
    * I tried just `products` for the route 
    * and still receive the error.
    */
    $this->get(route('api.products'));
    $this->assertResponseOk();
}

Any other ideas?

Michael
  • 2,016
  • 5
  • 35
  • 51
  • 2
    if you're going to use `Route::resource()` you nee to use `php artisan make:controller ProductController --resource`. There are several functions missing from your controller method that `Route::resource()` requires. – Ohgodwhy Mar 17 '17 at 16:56

3 Answers3

1

You missed $this:

public function testProductsList(){
    $this->get(route('products'));
    $this->assertResponseOk();
}

Btw, it is not a unittest. See What's the difference between unit, functional, acceptance, and integration tests?

Community
  • 1
  • 1
Alex Blex
  • 34,704
  • 7
  • 48
  • 75
1

Try php artisan route:list to get the names of the routes I suspect the name of the route is not products (perhaps its products.index or api.products.index), hence the error.

There are three ways to solve this:

  1. Update $this->get(route('products')); with the correct name of the route as displayed by the route list artisan command (e.g. $this->get(route('products.index'));)
  2. Instead of using the route helper function, refer to the route directly like so: $this->get('/api/products/index');
  3. Rename the routes with custom names like so:

    Route::resource('products', 'ProductController', 
        ['names' => ['index' => 'products.list', // etc...]]);
    

Then use $this->get(route('products.list'));

Paras
  • 9,258
  • 31
  • 55
  • I wanted to keep from hard coding the route into the test, just in case the route changed in the future, so I tried options 1 & 3, and though neither of them worked with these lines in the test method `$this->get(route('products.list')); $this->assertResponseOk();` (I got the previous error about `assertResponseOk()` being undefined), I got it to work with the adjusted code I listed above. Thank you! – Michael Mar 17 '17 at 17:28
0

You can edit Route::group like this:

Route::group(['prefix' => 'api', 'as' => 'api.'], function(){
    Route::resource('products', 'ProductController', ['only' => ['index', 'store',     'update']]);
});
phuongtt
  • 1
  • 1