Skip to content

Instantly share code, notes, and snippets.

@agm1984
Last active Jul 10, 2020
Embed
What would you like to do?
phpunit.xml for Laravel unit testing with database transactions. DB_CONNECTION and DB_DATABASE are omitted which implicitly instructs Laravel to use the database information in the currently-loaded .env file (note: we are testing against the current environment and the <php> section in this file overwrites specific env variables)
<?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"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="AppLayout">
<directory suffix="Test.php">./tests/AppLayout</directory>
</testsuite>
<testsuite name="Auth">
<directory suffix="Test.php">./tests/Auth</directory>
</testsuite>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<listeners>
<listener class="\Mockery\Adapter\Phpunit\TestListener"
file="vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListener.php">
</listener>
</listeners>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<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"/>
</php>
</phpunit>
@agm1984
Copy link
Author

agm1984 commented Jul 10, 2020

If DB_CONNECTION and DB_DATABASE are omitted, PHPUnit will respect the values from the currently-loaded .env file.

Then, in each test, you can use this pattern:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;

class SomeTest extends TestCase
{
    use DatabaseTransactions;

    // uncomment these if you want to use them, and mind the `: void` return type;
    // in Laravel 5.7+, return type of void is mandatory (to enforce covariance of void)

    /* public function setUp() : void
    {
        parent::setUp();

        // maybe something here
    }*/

    /* public function tearDown() : void
    {
        parent::tearDown();

        // maybe something here
    }*/

    /** @test */
    public function it_should_expect_an_assertion_is_true()
    {
        /*
            With `DatabaseTransactions` trait, PHPUnit will look to your `.env` file FIRST, then your
            `phpunit.xml` file (due to right-to-left-precedence) and then it will use database transactions
            on that currently loaded database. This means every time you do something that mutates
            data in the database, it will be mutated "in the transaction" and then after the unit test,
            the transaction will be rolled back. It is important to understand `transaction commit` and
            `transaction rollback` to fully appreciate this. You may need to change your testing strategy
            slightly, but each test by itself should not have dependencies or rely on any  system state,
            so this ideal matches up well with the idea of making a test occur in a transaction wrapper
            and then rolling it back after each test. 

            If any state does persist on you through tests, I recommend blaming Laravel first, and then check
            if it is maintaining any singletons or anything like that, possibly due to a session.
        */
    }
}

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment