As you saw in the previous lesson, we interact with the database, which creates actual data in an actual database, which is wrong because tests should be run separately. Kinda like simulating the database. We shouldn't interact with live databases at all. For that, we need to configure on which database our tests would run.
When creating a new Laravel project, you can choose the testing framework. But the configuration is made in the phpunit.xml
file for both frameworks.
And the database configuration is in two variables, which are commented out by default.
phpunit.xml:
<?xml version="1.0" encoding="UTF-8"?><phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true"> <testsuites> <testsuite name="Unit"> <directory suffix="Test.php">./tests/Unit</directory> </testsuite> <testsuite name="Feature"> <directory suffix="Test.php">./tests/Feature</directory> </testsuite> </testsuites> <php> <server name="APP_ENV" value="testing"/> <server name="BCRYPT_ROUNDS" value="4"/> <server name="CACHE_DRIVER" value="array"/> <!-- <server name="DB_CONNECTION" value="sqlite"/> --> <!-- <server name="DB_DATABASE" value=":memory:"/> --> <server name="MAIL_MAILER" value="array"/> <server name="QUEUE_CONNECTION" value="sync"/> <server name="SESSION_DRIVER" value="array"/> <server name="TELESCOPE_ENABLED" value="false"/> </php></phpunit>
You need to specify the connection and the database where your tests should be run. You can check what connections are available in the config/database.php
. For example, SQLite
, mysql
.
In most cases, running tests using the SQLite
connection and memory
as the database is pretty safe. You wouldn't need to create a separate database.
The Exception to using SQLite is if you use specific MySQL functions that SQLite doesn't support. Then, you will have errors.
Uncomment those two lines in the phpunit.xml
and re-run the tests. We get an error no such table: products
.
And of course. We specified a new connection and database but have not run the migrations. So, we need to run migrations on that database whenever we run the test. For that, Laravel has a trait, RefreshDatabase
. This trait will re-run migration every time this test is run.
tests/Feature/ProductsTest.php:
use Illuminate\Foundation\Testing\RefreshDatabase; class ProductsTest extends TestCase{ use RefreshDatabase; // ...}
Here, you need to be careful not to accidentally launch tests on a live database because this will refresh the database. Now, if we re-run the tests, we see all are green.
And if you look in the products
table on your live database, you will see that no new records were added.
In addition to phpunit.xml
, there is another way to configure env variables. Similar to what you do in .env
, you can create a separate .env.testing
.
Comment out the DB configuration in the phpunit.xml
file. Create a new file .env.testing
with the same content as in .env
.
Now we can change the DB connection and database in the .env.testing
. When the tests are run, the DB connection settings will be taken from .env.testing
.
.env.testing:
APP_NAME=LaravelAPP_ENV=localAPP_KEY=base64:Oo7mTQpSW00WmjWs1kJVjqFZw/oQVENUxyhuyLCQgfk=APP_DEBUG=trueAPP_URL=http://localhost LOG_CHANNEL=stackLOG_LEVEL=debug DB_CONNECTION=sqlite DB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=:memory: DB_USERNAME=rootDB_PASSWORD= // ...
It's your preference whether to use phpunit.xml
or .env.testing
.