Laravel - Test with Artisan seed fails - laravel

I am trying to be able to load seed data inside of a Laravel test case but I keep encountering the error below.
<?php
namespace Tests\Feature;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class MagicTest extends TestCase
{
protected function setUp(): void
{
Artisan::call('db:seed');
}
public function test_show()
{
echo 'hi';
}
}
But when I try by running php artisan test
RuntimeException
A facade root has not been set.
at vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:334
How can I make this work? Or should I be taking a completely different approach?

Related

PHPUnit tests failing after adding a ViewServiceProvider for sharing data to views

I am relatively new to testing so please forgive me if this a stupid question.
All my tests are failing after I added a ViewServiceProvider to share data with the views.
The error is:
Illuminate\Database\QueryException : SQLSTATE[HY000]: General error: 1 no such table: policies (SQL: select "name", "slug" from "policies")
My tests are making use the the refresh database trait:
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
use RefreshDatabase;
...
}
Here is an example of the ViewServiceProvider:
namespace App\Providers;
use App\Models\Policy;
use Illuminate\Support\ServiceProvider;
class ViewServiceProvider extends ServiceProvider
{
public function register(): void{...}
public function boot(): void
{
view()->share('policies', Policy::all(['name', 'slug']));
}
}
Every works when browsing the site on front end. Am i missing something? Why are the tests failing?
I will appreciate suggestions on how to make the tests pass.
Edit
It makes total sense what #Donkarnash said but it's also confusing because according to the docs:
So, what if we need to register a view composer within our service provider? This should be done within the boot method. This method is called after all other service providers have been registered, meaning you have access to all other services that have been registered by the framework
See https://laravel.com/docs/8.x/providers#the-boot-method
I found the solution. Creating a view composer solved the problem.
namespace App\Http\View\Composers;
use App\Models\Policy;
use Illuminate\View\View;
class PolicyComposer
{
public function compose(View $view): void
{
$view->with('policies', Policy::all(['name', 'slug']));
}
}
Then I referenced the composer in the ViewServiceProvider
namespace App\Providers;
use App\Models\Policy;
use Illuminate\Support\ServiceProvider;
class ViewServiceProvider extends ServiceProvider
{
public function register(): void{...}
public function boot(): void
{
view()->composer('*', PolicyComposer::class);
}
}

Why doesn't PHPUnit see Laravel Facades?

I have problem with PHPUnit testing and Laravel
Exception: Class 'DB' not found
My TestCase file:
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
}
My CreatesApplication file:
namespace Tests;
use Illuminate\Contracts\Console\Kernel;
trait CreatesApplication
{
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
return $app;
}
}
This is my Test:
namespace Tests\Unit;
use App\Services\RepetitionService;
use PHPUnit\Framework\TestCase;
class RepetitionServiceTest extends TestCase
{
public function testGetNextIteration()
{
$repetitionService = new RepetitionService;
$nextIteration = $repetitionService->getNextIteration(1);
$this->assertEquals(2, $nextIteration);
}
}
Method that is being tested:
public function getNextIteration(int $lastIteration) : int
{
// some example code (method is not real but code below copied from original method)
\DB::table('cards')->get();
Config::get('params.repeat_iterations');
config('params.repeat_iterations');
}
Commend:
php vendor/phpunit/phpunit/phpunit --configuration phpunit.xml tests/Unit
Versions:
laravel 7
PHP 7.4
PHPUnit 9
Try to use DB from this path
use Illuminate\Support\Facades\DB;

Laravel Testing/phpunit, Too few arguments passed when using dependency injection

I'm trying to create a simple test with Laravel. My test code is as below;
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Http\Controllers\Abc\AbcController;
class AbcTest extends TestCase
{
/**
* A basic test example.
*
* #return void
*/
private $abcController;
public function __construct (AbcController $abcController) {
$this->abcController = $abcController;
}
public function testExample()
{
$this->assertTrue(true);
}
However, when i run the test, i'm hitting this error,
PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function Tests\Feature\abc::__construct(), 0 passed in /var/www/nex/backend/vendor/phpunit/phpunit/src/Framework/TestSuite.php on line 151 and exactly 1 expected in /var/www/nex/backend/tests/Feature/abc.php:28
I've been using this method of performing dependency injections for the rest of my project. I'm not sure why its not working on this particular code.
All help is appreciated.
Thanks!
Check https://laravel.com/docs/5.8/testing you should not use Dependency Injection on controller. Instead you should call the endpoint.
Example
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Http\Controllers\Abc\AbcController;
class AbcTest extends TestCase
{
public function testExample()
{
$response = $this->get('/url');
$response->assertOk();
}
}

cartalyst extensions' routes only set after first test

Please help I'm using Laravel 5.5 with Cartalyst Platform 7.0 and Phpunit 6.0. I have been trying a lot to install extensions in a testing environment but when the first test runs the extensions routes are not defined so the test returns 404. The second test and the rest of the tests pass because the routes now exist. If I echo(count(\Route::getRoutes())) the first test it is 11 and the rest it is 329.
TestCase
<?php
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Support\Facades\Artisan;
use Sentinel;
abstract class TestCase extends BaseTestCase
{
use TestData, CreatesApplication;
public function setUp()
{
parent::setUp();
$this->app['Illuminate\Contracts\Http\Kernel']->disableMiddleware();
Sentinel::getUserRepository()->setModel(\App\Models\User::class);
Sentinel::getPersistenceRepository()->setUsersModel(\App\Models\User::class);
$this->setUpDatabase();
}
protected function setUpDatabase()
{
Artisan::call('migrate');
Artisan::call('extension:install');
Artisan::call('extension:enable');
}
}

How can call artisan commands before Test:suite

Is there a way to call artisan commands before my entire test suite? Installing Cartalyst extensions takes time so I do not want to do it before every test but I am presuming i cannot call facades from a static method like setUpBeforeClass, I receive this error
RuntimeException: A facade root has not been set. in /Users/lance/Desktop/FastLMS/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:218
<?php
namespace Tests;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Support\Facades\Artisan;
class TestCase extends \Illuminate\Foundation\Testing\TestCase
{
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
Artisan::call('migrate');
Artisan::call('extension:install');
Artisan::call('extension:enable');
}
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
Hash::setRounds(4);
return $app;
}
public function setUp()
{
parent::setUp();
$this->app['Illuminate\Contracts\Http\Kernel']->disableMiddleware();
}
}

Resources