are all of your tests use Laravel TestCase ?
PHPUnit says route not defined
Hi! If I run a test on a specific file and all the tests in it. PHPUnit says routes exists. But if I run all tests on all files in the Tests directory, PHPUnit fails with route not being defined. Same happens in PHPStorm as on the command line.
Anyone know why this occurs?
Having this same problem. Routes are found on the first test, but not on the subsequent tests.
Have you tried flushing events between tests? In my TestCase that all of my testing methods extend, I have a resetEvents method that gets called between each test which flushes event listeners as such:
/**
* Flush and reboot Eloquent model events.
*
* Model events only get fired once per test suite without this.
*
* @see https://github.com/dwightwatson/validating/tree/0.10#testing
*
* @return void
*/
public function resetEvents()
{
foreach ($this->getModelsWithFlushEventListenersMethod() as $model)
{
call_user_func([$model, 'flushEventListeners']);
call_user_func([$model, 'boot']);
}
}
/**
* Find all of the models that have the flushEventListeners method.
* This is because of an issue with Laravel's unit testing behavior.
* Gotta flush the event listeners after every test; make sure to revise this
* method when adding more hierarchies to the app. #sux
*
* @see https://github.com/laravel/framework/issues/1181
*
* @return array
*/
protected function getModelsWithFlushEventListenersMethod()
{
$files = File::allFiles(base_path() . '/app/myAppNamespace');
$models = [];
foreach ($files as $file)
{
if (preg_match('`Users`', pathinfo($file, PATHINFO_DIRNAME)))
{
$model = 'myAppNamespace\\Users\\' . pathinfo($file, PATHINFO_FILENAME);
}
else
{
$model = 'myAppNamespace\\' . pathinfo($file, PATHINFO_FILENAME);
}
try
{
$rc = new ReflectionClass($model);
if ($rc->hasMethod('flushEventListeners'))
{
$models[] = $model;
}
} catch (ReflectionException $e)
{
//Log::warning($e->getMessage());
}
}
return $models;
}
I tried that, but no luck so far. The problem that I'm having is that in the first test all routes can be found. Something like:
public function testFirstTime()
{
$this->route('GET', 'index');
$this->assertResponseOk();
}
The route index is found and the test is run. But on the next test, for example:
public function testSecondTime()
{
$this->route('GET', 'user.index');
$this->assertResponseOk();
}
Throws InvalidArgumentException: Route [user.index] not defined. And that route is defined, it's shown when I run php artisan route:list. Super weird.
@noboxdev It looks like you are trying to call the index method of your user resource, which is not a route. If you want to test the route, you should use:
$this->call('GET', 'user');
$this->assertResponseOk();
If you want to test the controller, you should use:
$this->action('GET', 'UserController@index');
$this->assertResponseOk();
This may be defined in your routes, but it's all about where it is. If user.index is defined under the 'Name' category, then the value under the 'URI' category is what you really want to test with the call. Likewise, if you want to test the controller, then the value under 'Action' is what you should be testing for. If you want to call it like you are, you may have to explicitly name the route in your routes.php file.
@noboxdev Is it resource controller?
If so, then it's users.index, so try this:
public function testSecondTime()
{
$this->route('GET', 'users.index');
$this->assertResponseOk();
}
Yes, it's a resource controller. But it seems like routes and urls are not found after the first test. Something to do with application bootstrapping on subsequent tests? Here's what's happening on my ExampleTest.
<?php
class ExampleTest extends TestCase {
/**
* A basic functional test example.
* This test runs ok.
*
* @return void
*/
public function testBasicExample()
{
$response = $this->call('GET', '/');
$this->assertEquals(200, $response->getStatusCode());
}
/**
* Exactly the same test. But the url returns a 404 page.
*
* 1) ExampleTest::testBasicExampleAgain
* Failed asserting that 404 matches expected 200.
*
* @return void
*/
public function testBasicExampleAgain()
{
$response = $this->call('GET', '/');
$this->assertEquals(200, $response->getStatusCode());
}
}
Weird behavior isn't it? Or am I missing something?
Am also finding the same problem while unit testing. Has any one found a solution to this? The example below would show an error on url not found in testBasicExampleAgain()
<?php
class ExampleTest extends TestCase {
/**
* A basic functional test example.
* This test runs ok.
*
* @return void
*/
public function testBasicExample()
{
$response = $this->call('GET', '/');
$this->assertEquals(200, $response->getStatusCode());
}
/**
* Exactly the same test. But the url returns a 404 page.
*
* 1) ExampleTest::testBasicExampleAgain
* Failed asserting that 404 matches expected 200.
*
* @return void
*/
public function testBasicExampleAgain()
{
$response = $this->call('GET', '/');
$this->assertEquals(200, $response->getStatusCode());
}
}
When you change the structure to the example below it works.
class ExampleTest extends TestCase {
/**
* A basic functional test example.
* This test runs ok.
*
* @return void
*/
public function testBasicExample()
{
$response = $this->call('GET', '/');
$this->assertEquals(200, $response->getStatusCode());
$response = $this->call('GET', '/');
$this->assertEquals(200, $response->getStatusCode());
}
The second call to the url '/' works with no errors but when separated to different tests url is not found. So is there a way to avoid this and work with separate tests and still be able to call same url more than once.
I was running into this exact same problem this morning. However, last night everything was hunky-dorey - all tests green. The change I made which caused the same InvalidArgumentException (route not found) was to chop up my routes file into partials and require each one within routes.php. Did this as my routes file was starting to get a little unweidly.
Weirdly, the routes themselves all worked just fine if I manually visited them and everything was fine when I ran php artisan route:list. It was just the phpunit tests that were failing. When I switched back to my original routes file everything went back to green.
Not sure whether those above with similar issues have done something similar to their routes file but if so then it might be the cause of the failing tests (not really a solution though I'm afraid...)
in my cast i have defined the routes with fully qualified name e.g.
Route::resource('/users', '\App\Http\Controllers\<Folder>\<Folder>\UserController');
The Application self is Ok, all Routes will be found
but in the UnitTests
$this->action('GET', '\App\Http\Controllers\<Folder>\<Folder>\UserController@index');
this throw an Error:
InvalidArgumentException: Action App\Http\Controllers<Folder><Folder>\UserController@index not defined
if i change
Route::resource('/users', '\App\Http\Controllers\<Folder>\<Folder>\UserController');
to
Route::resource('/users', '<Folder>\<Folder>\UserController');
everything is fine
I was having this same issue. In my service provider I had
require_once('routes.php');
I changed it to
require('routes.php');
I fixed the issue by using Guzzle.
Thank you @rbtmtn!
Thank you @FourStacks I have been scratching my head over this for hours. My issue was also splitting my routes files into multiple seperate files. After putting all my routes into a single file "again", it fixed the issue.
Thank you @rbtmtn indeed! Changing require_once to require solved it
I assume that it needs to be able to require the file multiple times within one test session. I've spent way too much time on this :(
My 5 cents - I have discovered that my test with the line:
$this->call('GET', "http:....."); $this->assertRedirectedToRoute('login');
only works successfully if it is the first on in the unit-test file. Even if I put another dummy test-function before the routing test, with the code like this:
$this->assertTrue(true);
Than, My test with "assertRedirectedToRoute" fails.
So I think it is a kind of bug in flushing/tearDown functions. I use Laravel 5.1 on homestead Current PHP version: 5.6.13.
@rbtmtn solution worked! =) Thanks!
Just ran into the same issue. I had split my routes into multiple files. However, I had originally used require, but switched to require_once because in one of the routes files I had added a function that got re-defined when I ran the tests. So I'd switched to require_once. By extracting this helper function into a separate file the errors went away.
Hi, I had the problem that calling the URL .../api/products was working fine in a browser but in phpunit test the route (it goes to the resource controller index function): $this->get(route('api.products.index')) ->assertResponseOk(); did not work:
InvalidArgumentException: Route [api.products.index] not defined.
I listed the routes via 'php artisan route:list' and there I found the Name column that says: 'products.index'
So setting the test route to it worked! I hope it helps :)
@rbtmtn solution worked for me too.
For those having this problem, if you, like me, followed Laracasts on splitting the routes web.php file into multiple partials like so:
/** @var File $partial */
foreach (File::allFiles(__DIR__ . '/partials/web') as $partial) {
require_once $partial->getPathname();
}
To fix, you just need to make the "require_once" be just "require".
@saifulss Thanks it helped.
@FourStacks, @rbtmtn yours both decisions are correct. I have got the same problem with phpunit using my routes file. Routes were splitted to separate files and were included in routes.php via "require_once". I changed it to "require" and the problem is gone. The same result via push back splitted routes into main routes file. But in my case, simply change "require_once" to "require" is more convenient decision. Thank you!
@dimsav I had the same stupid mistake. I had split my routes into different files and this was happening.
Thanks for the catch :)
@RBTMTN - That was it... thank you!
Please or to participate in this conversation.