Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create an in-memory database for PHPUnit testing?

I'm a newcomer to PHPUnit (and unit testing in general). I want to work on a test suite that developers can run locally, but can also be run in our integration system (Codeship). I understand that it is possible to use an in-memory database, but it seems like that relies on the migrations, which we are not using (doesn't seem to handle views, stored procedures, functions, triggers, etc very well?).

What's the best way (place in Laravel) to 1) create a database in memory and seed the database with default data (to be used for ALL test)?

like image 670
QuietSeditionist Avatar asked Jun 19 '19 18:06

QuietSeditionist


People also ask

Where do I put PHPUnit test?

You can run all the tests in a directory using the PHPUnit binary installed in your vendor folder. You can also run a single test by providing the path to the test file.

Is MySQL in memory?

MEMORY is a storage engine for MySQL and MariaDB relational database management systems, developed by Oracle and MariaDB. Before the version 4.1 of MySQL it was called Heap. The SHOW ENGINES command describes MEMORY as: Hash based, stored in memory, useful for temporary tables. MEMORY writes table data in-memory.

What is PHPUnit setUp?

PHPUnit supports sharing the setup code. Before a test method is run, a template method called setUp() is invoked. setUp() is where you create the objects against which you will test. Once the test method has finished running, whether it succeeded or failed, another template method called tearDown() is invoked.


2 Answers

You can use SQLite.

From the docs:

An SQLite database is normally stored in a single ordinary disk file. However, in certain circumstances, the database might be stored in memory.

Add this to the config/database.php file:

'sqlite_testing' => [
    'driver'   => 'sqlite',
    'database' => ':memory:',
    'prefix'   => '',
],

On the phpunit.xml file, under <php> node:

<env name="DB_CONNECTION" value="sqlite_testing" />

Read more here.

Other solution

Create a testing database on your storage/ folder, with the name database.sqlite or if you want another name or another location you have to change the configs on the config/database.php file, these are the default configs:

'sqlite' => [
    'driver'   => 'sqlite',
    'database' => storage_path('database.sqlite'),
    'prefix'   => '',
],

Use this command to run your migrations:

php artisan migrate --database=sqlite

Or add this line to the .env file:

DB_CONNECTION=sqlite

Your application is using sqlite for phpunit.

Now you can run your migrations and test. After that, just change the DB_CONNECTION to the database you are using for your project.

like image 173
Mateus Junges Avatar answered Oct 03 '22 14:10

Mateus Junges


This isn't an answer you may be looking for but more of an alternative solution to consider.

From my experiences, I've found the path of least resistance is to actually mock your models (or the query builder if you are using that) and have them return the results you need them to.

When developing tests, you should always be thinking about what dependencies can be removed entirely from the test so you can keep your focus on only what you are trying to test at that time.

There are also likely going to be nuances (most likely very minor) between running an in-memory database vs how your production database will be working which will ultimately hurt the integrity of your tests and may end up even giving you false-positives. This will be especially true if you are using the query builder and you may end up needing to actually develop different queries (different syntaxes between MySQL and sqlite for example) depending on what environment you the query itself to even work.

like image 40
user1669496 Avatar answered Oct 03 '22 15:10

user1669496