I use PHPUnit with code coverage on my Laravel 5 project on MAC OS X 10.9.5. I wrote a test class for a client profile page as follows.
<?php
use Illuminate\Foundation\Testing\DatabaseMigrations;
class MinimalViewTest extends TestCase
{
use DatabaseMigrations;
public function testWithSegFault()
{
...
$this->actingAs($userAuthorized)
->visit('/clients/profile/x11')
->visit('/clients/profile/' . $randomUser->id);
}
}
The test visits two different pages as an authorized user. The first visit to /clients/profile/x11 succeeds. However, the second visit ends in a segmentation fault.
$ vendor/bin/phpunit -v tests/MinimalViewTest.php
PHPUnit 5.0.10 by Sebastian Bergmann and contributors.
Runtime: PHP 7.0.0 with Xdebug 2.4.0
Configuration: /.../phpunit.xml
Segmentation fault: 11
If I call PHPUnit with no code coverage, the test succeeds.
$ vendor/bin/phpunit -v tests/MinimalViewTest.php --no-coverage
PHPUnit 5.0.10 by Sebastian Bergmann and contributors.
Runtime: PHP 7.0.0 with Xdebug 2.4.0
Configuration: /.../phpunit.xml
. 1 / 1 (100%)
Time: 1.71 seconds, Memory: 16.00Mb
OK (1 test, 3 assertions)
Besides the authentication provided by Laravel 5, I use my own middleware to determine the user group.
Route::group(['middleware' => ['web', 'auth', 'usergroup'], 'groups' => ['admin', 'orgateam']], function ()
{
Route::get('/clients/profile/{clientsId}', ['as' => 'clientsProfileByClientId', 'uses' => 'ClientsController#profileByClientId']);
});
The middleware I use is as follows.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth as Auth;
class UserGroupMiddleware
{
public function handle($request, Closure $next)
{
return $next($request);
}
}
I could track the issue down to the call $next($request) that raises the segmentation fault. However, I am able to var_dump both objects $next and $request with no problem.
I used gdb to find more hints on why the segmentation fault occurs. It points me to
Program received signal SIGSEGV, Segmentation fault.
0x00007fff88a7fd13 in _platform_strcmp ()
from /usr/lib/system/libsystem_platform.dylib
What is happening here precisely? Is there really an issue with the Authentication of Laravel 5 and PHPUnit code coverage? I would really like to use code coverage along with PHPUnit.
Related
I'm running Laravel 5.8 and this function isn't working for my tests. I've put it in the individual tests as the laracast video shows and i've also put it in the setup method. I'm still getting Failed asserting that 500 matches expected 201 type errors without a stacktrace. Anybody know why this could be?
PHPUnit 7.5.20 by Sebastian Bergmann and contributors
/** #test */
public function test_name(){
$this->withoutExceptionHandling();
$response = $this->post("path/url/");
$this->assertEquals(201, $response->getStatusCode());
}
I use Laravel 5.8 and phphunit version 7.5. When I run PHPUnit with error, show me error but when not has error show me only this line
PHPUnit 7.5.0 by Sebastian Bergmann and contributors.
My test class:
use Tests\TestCase;
class leadTest extends TestCase
{
public $Array= ['lead_name' => 'Jon','lead_family'=>'Doe'];
public function test_store()
{
$this->withoutExceptionHandling();
$this->post('leads', $this->Array());
$this->assertDatabaseHas('leads', $this->Array);
}
}
That is the reason of your error:
$this->withoutExceptionHandling();
Try without it.
Look also at class name it should be: LeadTest, and the file should be named LeadTest.php
Laravel 6.5
Laravel Browser Kit ^5.1
I am creating my own packages for something I building and one is causing the issue at hand: A facade root has not been set. when I run my tests.
This is routes file App\Game\routes\web.php:
<?php
use Illuminate\Support\Facades\Route;
// Core routes for the game related stuff:
Route::get('/game', ['as' => 'game', 'uses' => 'GameController#game']);
Pretty basic, nothing here that should stand out. So how do we register these:
<?php
namespace App\Game\Providers;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RoutesProvider extends ServiceProvider
{
protected $namespace = 'App\Game\Controllers';
public function boot()
{
parent::boot();
}
public function map()
{
$this->mapWebRoutes();
}
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace)
->group(__DIR__.'/../routes/web.php');
}
}
Again nothing insane, if we addd this to the config/app.php and run php artisan route:list we see:
You can see the game route above. so now lets run our tests, make sure nothings breaking ...
composer phpunit
> ./vendor/bin/phpunit --coverage-html=./test-coverage
PHPUnit 8.4.3 by Sebastian Bergmann and contributors.
Fatal error: Uncaught RuntimeException: A facade root has not been set. in /Users/xxxx/Documents/xxxx/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:242
Stack trace:
#0 /Users/xxxx/Documents/xxxx/app/Game/routes/web.php(5): Illuminate\Support\Facades\Facade::__callStatic('get', Array)
#1 /Users/xxxx/Documents/xxxx/vendor/phpunit/php-code-coverage/src/CodeCoverage.php(955): include_once('/Users/adambala...')
#2 /Users/xxxx/Documents/xxxx/vendor/phpunit/php-code-coverage/src/CodeCoverage.php(239): SebastianBergmann\CodeCoverage\CodeCoverage->initializeData()
#3 /Users/xxxx/Documents/xxxx/vendor/phpunit/phpunit/src/Framework/TestResult.php(646): SebastianBergmann\CodeCoverage\CodeCoverage->start(Object(Tests\Unit\xxxx\BaseStatValueTest))
#4 /Users/xxxx/Documents/xxxx/vendor/phpunit/phpunit/src/Framework/TestCase.php(752): PHPUnit\Framework\TestResult->run(Object(Tests\Unit\xxxx\BaseStatValueTest))
#5 /Users/xxxx/Documents/xxxx/vendor/phpunit/phpunit/src/Framewor in /Users/xxxx/Documents/xxxx/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php on line 242
PHP Fatal error: Uncaught RuntimeException: A facade root has not been set. in /Users/xxxx/Documents/xxxx/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:242
Stack trace:
#0 /Users/xxxx/Documents/xxxx/app/Game/routes/web.php(5): Illuminate\Support\Facades\Facade::__callStatic('get', Array)
#1 /Users/xxxx/Documents/xxxx/vendor/phpunit/php-code-coverage/src/CodeCoverage.php(955): include_once('/Users/adambala...')
#2 /Users/xxxx/Documents/xxxx/vendor/phpunit/php-code-coverage/src/CodeCoverage.php(239): SebastianBergmann\CodeCoverage\CodeCoverage->initializeData()
#3 /Users/xxxx/Documents/xxxx/vendor/phpunit/phpunit/src/Framework/TestResult.php(646): SebastianBergmann\CodeCoverage\CodeCoverage->start(Object(Tests\Unit\xxxx\BaseStatValueTest))
#4 /Users/xxxx/Documents/xxxx/vendor/phpunit/phpunit/src/Framework/TestCase.php(752): PHPUnit\Framework\TestResult->run(Object(Tests\Unit\xxxx\BaseStatValueTest))
#5 /Users/xxxx/Documents/xxxx/vendor/phpunit/phpunit/src/Framewor in /Users/xxxx/Documents/xxxx/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php on line 242
Its all caused by that web.php routes file when it tries to create the route doing: Route::get(....). From my understanding router does not exist in app container when the app boots up for test.
I have tried calling setUp in my test classes, and calling it's parent. But still I get the error.
I have never encountered this before and nothing o the internet is helping me. Any ideas as to why I am getting this error?
Exclude the routes folder on phpunit coverage tests:
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
<exclude>
<directory>./app/Game/routes</directory>
</exclude>
</whitelist>
</filter>
I am trying to recreate the database before each test in some PHPUnit test cases. I am using Laravel 5.3. Here is TestCase:
class CourseTypesTest extends TestCase
{
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed', ['--class' => 'TestDatabaseSeeder ', '--database' => 'testing']);
}
/**
* A basic functional test example.
*
* #return void
*/
public function test_list_course_types()
{
$httpRequest = $this->json('GET', '/api/course-types');
$httpRequest->assertResponseOk();
$httpRequest->seeJson();
}
public function tearDown()
{
Artisan::call('migrate:reset');
parent::tearDown();
}
}
Running phpunit fails with error:
$ phpunit PHPUnit 5.7.5 by Sebastian Bergmann and contributors.
E 1 /
1 (100%)
Time: 2.19 seconds, Memory: 12.00MB
There was 1 error:
1) CourseTypesTest::test_list_course_types ReflectionException: Class
TestDatabaseSeeder does not exist
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Container\Container.php:749
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Container\Container.php:644
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Foundation\Application.php:709
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Database\Console\Seeds\SeedCommand.php:74
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Database\Console\Seeds\SeedCommand.php:63
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php:2292
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Database\Console\Seeds\SeedCommand.php:64
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Container\Container.php:508
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Console\Command.php:169
D:\www\learn-laravel\my-folder-api\vendor\symfony\console\Command\Command.php:254
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Console\Command.php:155
D:\www\learn-laravel\my-folder-api\vendor\symfony\console\Application.php:821
D:\www\learn-laravel\my-folder-api\vendor\symfony\console\Application.php:187
D:\www\learn-laravel\my-folder-api\vendor\symfony\console\Application.php:118
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Console\Application.php:107
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php:218
D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php:237
D:\www\learn-laravel\my-folder-api\tests\rest\CourseTypesTest.php:17
ERRORS! Tests: 1, Assertions: 0, Errors: 1.
but this class exists:
Since version 5.8 you can do:
// Run the DatabaseSeeder...
$this->seed();
// Run a single seeder...
$this->seed(OrderStatusesTableSeeder::class);
Take a look at the documentation
The DatabaseSeeder can be instantiated on its own, and its call method is public.
All you need to do in your CourseTypesTest class would be
(new DatabaseSeeder())->call(TestDatabaseSeeder::class);
Or you can make use of Laravel's app helper as follow
app(DatabaseSeeder::class)->call(TestDatabaseSeeder::class);
The problem is empty space in your --class argument. If you take close look at array '--class' => 'TestDatabaseSeeder ' there is space in the end ... this is the problem. Change it to '--class' => 'TestDatabaseSeeder' and it should work fine.
You can try this way. You can execute this command when you run your test.
Please explain why Laravel 4's example test fails for me.
My "/" route redirects to "login" in my routes.php file.
(Oh, I've RTFMed and scoured several sites, blogs, and tuts.)
-sh-3.2$ phpunit
PHPUnit 4.0.7 by Sebastian Bergmann.
Configuration read from /home/dev/phpunit.xml
The Xdebug extension is not loaded. No code coverage will be generated.
F
Time: 83 ms, Memory: 13.50Mb
There was 1 failure:
1) ExampleTest::testBasicExample
Failed asserting that false is true.
/home/dev/app/tests/ExampleTest.php:14
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
-sh-3.2$
Here is the code from ExampleTest.php
<?php
class ExampleTest extends TestCase {
/**
* A basic functional test example.
*
* #return void
*/
public function testBasicExample()
{
$crawler = $this->client->request('GET', '/');
$this->assertTrue($this->client->getResponse()->isOk());
}
}
The test is failing because you're getting 302 status code instead of 200 (since there is a redirection that wasn't in the default routes.php file).
If you want to test redirection, then Laravel provides several methods just for that.
If you're using named routes:
$this->assertRedirectedToRoute('login');
If not:
$this->assertRedirectedTo('login');
For testing response status codes:
$this->assertResponseStatus(302);