laravel / lumen-framework

The Laravel Lumen Framework.
https://lumen.laravel.com
MIT License
1.48k stars 419 forks source link

In a test case, when calling a route while omitting a required param throws an exception instead of returning 404. #891

Closed kanidjar closed 5 years ago

kanidjar commented 5 years ago

Description:

In a test case, when calling a route while omitting a required param throws an exception instead of returning 404.

 +exception: Symfony\Component\Debug\Exception\FatalThrowableError {#42
    -originalClassName: "ArgumentCountError"
    #message: "Too few arguments to function App\Http\Controllers\ExampleController::show(), 0 passed and exactly 1 expected"
    #code: 0
    #file: "./app/Http/Controllers/ExampleController.php"
    #line: 17
    #severity: E_RECOVERABLE_ERROR
    trace: {
      ./app/Http/Controllers/ExampleController.php:17 {
        › 
        › public function show($id) {
        ›     
      }
      App\Http\Controllers\ExampleController->show() {}
      ./vendor/illuminate/container/BoundMethod.php:32 { …}
      ./vendor/illuminate/container/BoundMethod.php:90 { …}
      ./vendor/illuminate/container/BoundMethod.php:34 { …}
      ./vendor/illuminate/container/Container.php:580 { …}
      ./vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php:376 { …}
      ./vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php:342 { …}
      ./vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php:316 { …}
      ./vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php:278 { …}
      ./vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php:263 { …}
      ./vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php:165 { …}
      ./vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php:416 { …}
      ./vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php:171 { …}
      ./vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php:91 { …}
      ./vendor/laravel/lumen-framework/src/Testing/Concerns/MakesHttpRequests.php:343 { …}
      ./vendor/laravel/lumen-framework/src/Testing/Concerns/MakesHttpRequests.php:65 { …}
      ./tests/ExampleTest.php:15 { …}
      ./vendor/phpunit/phpunit/src/Framework/TestCase.php:1153 { …}
      ./vendor/phpunit/phpunit/src/Framework/TestCase.php:842 { …}
      ./vendor/phpunit/phpunit/src/Framework/TestResult.php:687 { …}
      ./vendor/phpunit/phpunit/src/Framework/TestCase.php:796 { …}
      ./vendor/phpunit/phpunit/src/Framework/TestSuite.php:746 { …}
      ./vendor/phpunit/phpunit/src/Framework/TestSuite.php:746 { …}
      ./vendor/phpunit/phpunit/src/TextUI/TestRunner.php:641 { …}
      ./vendor/phpunit/phpunit/src/TextUI/Command.php:206 { …}
      ./vendor/phpunit/phpunit/src/TextUI/Command.php:162 { …}
      ./vendor/phpunit/phpunit/phpunit:61 { …}
    }
  }
}

Steps To Reproduce:

Routes

<?php

$router->get('/{id}', [ 'as' => 'show', 'uses' => 'ExampleController@show' ]);

Controller

<?php

namespace App\Http\Controllers;

class ExampleController extends Controller
{
    public function show($id) {
    }
}

Test

<?php

use Laravel\Lumen\Testing\DatabaseMigrations;
use Laravel\Lumen\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{

    public function testExample()
    {
       // Omitting required param in "show" route
        $this->get(route('show'));
    }
}
ProteanCode commented 5 years ago

Shouldn't it be

/{id?}

instead of

/{id}

and

public function show($id = null) {

instead of

public function show($id) {

?

kanidjar commented 5 years ago

No, in this case, the {id} is mandatory.

driesvints commented 5 years ago

I've tested this with the code above and I get a This test did not perform any assertions which is expected since you're not performing any assertions in the test method. The fact that you get an exception suggests there's more code in play. Are you sure this is the only modified code from a base Lumen installation?

kanidjar commented 5 years ago

The issue does not come from the test itself but from the app which throws an exception. Please have a look at your log file (or dump the response).

To me, it should return a 404 but an exception is thrown instead.

In your log file, you should see the following:

[2019-03-27 08:29:06] testing.ERROR: Symfony\Component\Debug\Exception\FatalThrowableError: Too few arguments to function App\Http\Controllers\ExampleController::show(), 0 passed and exactly 1 expected in C:\www\lumen\app\Http\Controllers\ExampleController.php:17
Stack trace:
#0 [internal function]: App\Http\Controllers\ExampleController->show()
#1 C:\www\lumen\vendor\illuminate\container\BoundMethod.php(32): call_user_func_array(Array, Array)
#2 C:\www\lumen\vendor\illuminate\container\BoundMethod.php(90): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#3 C:\www\lumen\vendor\illuminate\container\BoundMethod.php(34): Illuminate\Container\BoundMethod::callBoundMethod(Object(Laravel\Lumen\Application), Array, Object(Closure))
#4 C:\www\lumen\vendor\illuminate\container\Container.php(580): Illuminate\Container\BoundMethod::call(Object(Laravel\Lumen\Application), Array, Array, NULL)
#5 C:\www\lumen\vendor\laravel\lumen-framework\src\Concerns\RoutesRequests.php(376): Illuminate\Container\Container->call(Array, Array)
#6 C:\www\lumen\vendor\laravel\lumen-framework\src\Concerns\RoutesRequests.php(342): Laravel\Lumen\Application->callControllerCallable(Array, Array)
#7 C:\www\lumen\vendor\laravel\lumen-framework\src\Concerns\RoutesRequests.php(316): Laravel\Lumen\Application->callLumenController(Object(App\Http\Controllers\ExampleController), 'show', Array)
#8 C:\www\lumen\vendor\laravel\lumen-framework\src\Concerns\RoutesRequests.php(278): Laravel\Lumen\Application->callControllerAction(Array)
#9 C:\www\lumen\vendor\laravel\lumen-framework\src\Concerns\RoutesRequests.php(263): Laravel\Lumen\Application->callActionOnArrayBasedRoute(Array)
#10 C:\www\lumen\vendor\laravel\lumen-framework\src\Concerns\RoutesRequests.php(165): Laravel\Lumen\Application->handleFoundRoute(Array)
#11 C:\www\lumen\vendor\laravel\lumen-framework\src\Concerns\RoutesRequests.php(416): Laravel\Lumen\Application->Laravel\Lumen\Concerns\{closure}(Object(Laravel\Lumen\Http\Request))
#12 C:\www\lumen\vendor\laravel\lumen-framework\src\Concerns\RoutesRequests.php(171): Laravel\Lumen\Application->sendThroughPipeline(Array, Object(Closure))
#13 C:\www\lumen\vendor\laravel\lumen-framework\src\Concerns\RoutesRequests.php(91): Laravel\Lumen\Application->dispatch(Object(Laravel\Lumen\Http\Request))
#14 C:\www\lumen\vendor\laravel\lumen-framework\src\Testing\Concerns\MakesHttpRequests.php(343): Laravel\Lumen\Application->handle(Object(Laravel\Lumen\Http\Request))
#15 C:\www\lumen\vendor\laravel\lumen-framework\src\Testing\Concerns\MakesHttpRequests.php(65): Laravel\Lumen\Testing\TestCase->call('GET', 'http://localhos...', Array, Array, Array, Array)
#16 C:\www\lumen\tests\ExampleTest.php(12): Laravel\Lumen\Testing\TestCase->get('http://localhos...')
#17 C:\www\lumen\vendor\phpunit\phpunit\src\Framework\TestCase.php(1153): ExampleTest->testExample()
#18 C:\www\lumen\vendor\phpunit\phpunit\src\Framework\TestCase.php(842): PHPUnit\Framework\TestCase->runTest()
#19 C:\www\lumen\vendor\phpunit\phpunit\src\Framework\TestResult.php(687): PHPUnit\Framework\TestCase->runBare()
#20 C:\www\lumen\vendor\phpunit\phpunit\src\Framework\TestCase.php(796): PHPUnit\Framework\TestResult->run(Object(ExampleTest))
#21 C:\www\lumen\vendor\phpunit\phpunit\src\Framework\TestSuite.php(746): PHPUnit\Framework\TestCase->run(Object(PHPUnit\Framework\TestResult))
#22 C:\www\lumen\vendor\phpunit\phpunit\src\Framework\TestSuite.php(746): PHPUnit\Framework\TestSuite->run(Object(PHPUnit\Framework\TestResult))
#23 C:\www\lumen\vendor\phpunit\phpunit\src\TextUI\TestRunner.php(641): PHPUnit\Framework\TestSuite->run(Object(PHPUnit\Framework\TestResult))
#24 C:\Users\kanidjar\AppData\Roaming\Composer\vendor\phpunit\phpunit\src\TextUI\Command.php(206): PHPUnit\TextUI\TestRunner->doRun(Object(PHPUnit\Framework\TestSuite), Array, true)
#25 C:\Users\kanidjar\AppData\Roaming\Composer\vendor\phpunit\phpunit\src\TextUI\Command.php(162): PHPUnit\TextUI\Command->run(Array, true)
#26 C:\Users\kanidjar\AppData\Roaming\Composer\vendor\phpunit\phpunit\phpunit(61): PHPUnit\TextUI\Command::main()
driesvints commented 5 years ago

Aha, yeah that's normal because you're not passing any arguments to the route function. If you do $this->get(route('show', ['id' => 1])); in your test it should be ok. This error is expected.

driesvints commented 5 years ago

The way this works is different from Laravel because remember that Lumen uses a different router. If you don't pass an argument to the route function for a named route with a required argument it'll generate a route like this:

    dd(route('show')); // http://localhost/{id}