Testing Laravel 5 in memory

I am writing tests through behad for my large Laravel 5 project.

I have a test copy of my MySQL database in MySQL and a seeder for this database that shares some seeders from other environments. It all works as expected.

However, I tried to switch to using the in-memory sqlite database because it would significantly speed up my automatic tests, and because I run "artsian migrate: refresh --- seeder = TestDatabaseSeeder" at the beginning of each behavior scenario.

The problem I am facing is that some of my source data causes sqlite to throw a syntax error other than a descriptor, but MySQL is fully consistent with the seed data.

Ideally, I think I would like it to use MySQL in memory to achieve performance and to keep the database engine consistent. Is there an easy way with or without Laravel to use MySQL in memory when running tests? A solution that DOES NOT include duplicating and editing migration files in such a way as to make sqlite happy?

+5
source share
2 answers

It turned out that sqlite did not like how it "slipped away".

"\" needs to be replaced with "" ". And sqlite does not support enumerations, so I changed my migrations and used strings instead of enumerations.

0
source

Starting in 2019, there is now a way to create Laravel PHPunit tests for using a database in memory.

Configure SQLite In-memory for Laravel / Lumen tests

You should have the following:

  1. For all database migrations for all tables and files in your database, as is usually done for a real database, see the official Laravel migration documents .
  2. RefreshDatabase trait ( DatabaseMigrations trait for Lumen) in your PHPUnit test class (white papers ).
  3. Install the following in the config/database.php file in the connection section:
  'testing' => [ 'driver' => 'sqlite', 'database' => ':memory:', ], 
  1. Install the following line in the phpunit.xml file in the <php> section:
  <env name="DB_CONNECTION" value="testing"/> 

Thus, as soon as you run your PHPUnit tests, PHPUnit will read phpunit.xml , replace the .env DB_CONNECTION variable with testing . This will force you to use the testing database configuration (which is the database in memory).

Tests with a database in RAM against a disk database (in my experience) are about 5-30 times faster. The difference is 30 times for a small set of tests of ~ 200 CRUD tests, all of which fulfill database queries for half a dozen tables with some hasMany and belongsToMany .

And yes, migrations will be performed before and after each test, so you will start and finish working with a clean database after the tests are completed (this will have consequences if you add some data to the database on the disk and switch tests from time to time to work on dumb, not on the database in memory).

Fix SQLite Cannot add a NOT NULL column with default value NULL

You have now successfully set up in-memory database testing for your application. If you try to use foreign keys to cascade changes to some related tables, the above error is expected.

If you quickly switch your tests to the database on the disk (comment out <env name="DB_CONNECTION" value="testing"/> in your phpunit.xml file), the error will disappear. After switching back to the database in memory, make sure that the database on the disk is not empty. If so, run migrate:refresh and db:seed (here it is assumed that you have already prepared the database seeds you need) with artisan .

By default, SQLite disables foreign keys. To fix this, add the following snippets to your PHPUnit test class:

 // At the file top to import the DB facade use Illuminate\Support\Facades\DB; // In the setUp() method parent::setUp(); if (DB::connection() instanceof \Illuminate\Database\SQLiteConnection) { DB::statement(DB::raw('PRAGMA foreign_keys=on')); } 

See detailed explanations and other, better, different solutions here .

Hope this clarifies the topic enough to work without problems.

+1
source

All Articles