pixelpeter
4 years ago
41
2
Tips

How to set up and define your database for integration testing

Posted 4 years ago by pixelpeter

Despite the fact that "Laravel is build with testing in mind" I find this part not as intuitive as all the other great parts of the Laravel landscape. And the changes for the environment handling doens't make things easier.

I don't know if other devs see it the same way as I do.

So I'am willing to send a pull request to improve the documentation based on the response to this article.

For all the people who are struggling with phpunit and the integrated testing framework here's what to do.

Please keep in mind that most of this tips are related to seeding your database with seeders and not using model factories directly in your test methods to generate the minimal amount of data needed to get the test green.

1. Define you test database

config/database.php

This can be anything. MySQL, SQLite file based or like this example a SQLite db in memory

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

2. Let phpunit know which database to use

phpunit.xml

This was for me the hardest part to figure out.

You need tp add <env name="DB_CONNECTION" value="sqlite_testing" /> to the definition of environment vars like this.

Now phpunit nows witch connectin to use, because in comparison to codeception phpunit is not reading the .env.testing file .

  <php>
      <env name="APP_ENV" value="testing"/>
      <env name="CACHE_DRIVER" value="array"/>
      <env name="SESSION_DRIVER" value="array"/>
      <env name="QUEUE_DRIVER" value="sync"/>

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

3. Automatically migrate your database before each test

tests/[YOUR-TEST-FILE]

You can use the provided DatabaseMigrations trait

  use Illuminate\Foundation\Testing\WithoutMiddleware;
  use Illuminate\Foundation\Testing\DatabaseMigrations;
  use Illuminate\Support\Facades\Config;

  class [YOUR-TEST-CLASS] extends TestCase
  {
    use DatabaseMigrations;

  public function [YOUR-TEST-FUNCTION]()
  {
    // do your tests
  }
  ...

4. How to seed your database before each test

Because phpunits setUp() is called before the DatabaseMigrations trait you can't use it to seed the database.

So here are two options:

Don't use the DatabaseMigrations trait

You can write your own setUp() and tearDown() methods

tests/[YOUR-TEST-FILE]

  ...
  public function setUp()
  {
      parent::setUp();

      $this->artisan('migrate');
      $this->artisan('db:seed');
  }

  public function tearDown()
  {
      $this->artisan('migrate:reset');
  }
  ...

Use your own DatabaseMigrations trait

Write your own DatabaseMigrations trait with an extra call to db:seed.

tests/support/DatabaseMigrations.php

  trait DatabaseMigrations
  {
      /**
       * @before
       */
      public function runDatabaseMigrations()
      {
          $this->artisan('migrate');
          $this->artisan('db:seed');

          $this->beforeApplicationDestroyed(function () {
              $this->artisan('migrate:rollback');
          });
      }
  }

Don't forget do add it to composer.json for autoloading

  ...
  },
  "autoload-dev": {
      "classmap": [
          "tests/TestCase.php",
          "tests/support/DatabaseMigrations.php"
      ]
  },
  ...

5. Extra: How to define the database for functional testing with CodeCeption

In codeception for you functional suite you would set your database configuration in functional.suite.yml like this:

config:
  Laravel5:
    environment_file: .env.testing

6. Extra: How to use define the database for acceptance testing with Behat

The Laracasts Laravel Behat extension allows you to create a .env.behat file to change the environment variables.

This article helped me a lot to figure all this out:

http://stackoverflow.com/a/27986561

Maybe this is helpful for somebody.

If I am partly or even completely wrong please let me know so I can improve this article (and myself)

Please sign in or create an account to participate in this conversation.