简体   繁体   中英

Setting up Integration tests in a laravel package

Currently struggling to setup integration tests within a package I'm writing.

For the integrations tests I will need to have access to a Laravel environment so I can access things such as Artisan::call('migrate') and access the database.

Currently I'm guessing I need to have any tests extend the Laravel TestCase class, bootstrapping a Laravel environment. Although I cannot workout how I can call this file into my package.

Secondly while developing packages in workbench would I need to use Artisan::call('migrate', '--bench="vendor/package"') or Artisan::call('migrate', '--package="vendor/package"') this is confusing.

We need to create an instance of Laravel, along with a database that PHPUnit can access to run the tests against real-world data sets. Not brittle mocks. Firstly you should be developing your packages in isolation for a number of reasons, one being workbench is now deprecated in Laravel 5.

So firstly we need to dev-require the Laravel framework into our project:

"require-dev": {
    "phpunit/phpunit": "~4.0",
    "phpspec/phpspec": "~2.1",
    "laracasts/testdummy": "~2.0",
    "laravel/laravel": "dev-develop"
},   

Now we can create an abstract class called DbTestCase that all our tests will extend from. Within this class we will be spinning up an instance of Laravel and an in memory SQLite database for speed.

If we extend the native Laravel test class Illuminate\\Foundation\\Testing\\TestCase some of the work has already been done for us. We simple need to create a method that returns an instance of Illuminate\\Foundation\\Application .

/**
 * Boots the application.
 *
 * @return \Illuminate\Foundation\Application
 */
public function createApplication()
{
    $app = require __DIR__.'/../vendor/laravel/laravel/bootstrap/app.php';

    $app->register('Path\To\Your\PackageServiceProvider');

    $app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();

    return $app;        
}

notice the line $app->register('Path\\To\\Your\\PackageServiceProvider'); this is important. Include your package service provider path here, so we register it with our Laravel instance that lives in our packages /vendor folder.

Now we have a Laravel application running, we need to setup the in-memory SQLite database. Simple, Laravel's TestCase has a setUp() function that is run before ever test, lets do it there:

/**
 * Setup DB before each test.
 *
 * @return void  
 */
public function setUp()
{ 
    parent::setUp();

    $this->app['config']->set('database.default','sqlite'); 
    $this->app['config']->set('database.connections.sqlite.database', ':memory:');

    $this->migrate();
}

I won't give to much explanation as its quite readable. As you can see on the last line we are also calling $this->migrate() which obviously runs our migrations each time we run a test giving us a fresh DB to test against. Lets look at how that works:

/**
 * run package database migrations
 *
 * @return void
 */
public function migrate()
{ 
    $fileSystem = new Filesystem;
    $classFinder = new ClassFinder;

    foreach($fileSystem->files(__DIR__ . "/../src/Migrations") as $file)
    {
        $fileSystem->requireOnce($file);
        $migrationClass = $classFinder->findClass($file);

        (new $migrationClass)->up();
    }
}

Not to go into too much detail, basically what we are doing here is looking into the src/Migrations folder of the package requiring all the files and then running their migrations. Its rough and needs more safety checks (i will do that in the future) but it works.

Why not Artisan::call('migrate') ??

Simple! In Laravel 5 the command php artisan migrate --package='vendor/package' has been deprecated. Developers are now expected to create their own commands to generate and move migration files to the proper location in the application. This is a much more flexible approach.

Although this question already has an accepted answer, I strongly recommend to use the orchestra/testbench package.

Add this package in the require-dev section of your package's composer.json and make sure to extend any test class from this package's TestCase as described in the README.

This package is able to load custom Service Providers, register custom aliases, etc. while spinning up a complete Laravel environment for testing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM