Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel create database when testing

I am trying to run my unit test and create a database during setup. For some reason I am getting the error Unknown database 'coretest'. If I create the database though manually and run the test then I get Can't create database 'coretest'; database exists.

The drop database statement works just now the create database.

Here is my setUP and tearDown methods:

class TestCase extends Illuminate\Foundation\Testing\TestCase {
    /**
     * Default preparation for each test
     */

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

        DB::statement('create database coretest;');
        Artisan::call('migrate');
        $this->seed();
        Mail::pretend(true);
    }

    public function tearDown() {
        parent::tearDown();
        DB::statement('drop database coretest;');
    }
}
like image 526
ipengineer Avatar asked Jun 28 '13 20:06

ipengineer


2 Answers

The reason why you get this error is simply because laravel tries to connect to database specified in config, which doesn't exist.

The solution is to build your own PDO connection from the settings without specifying database (PDO allows this) and run CREATE DATABASE $dbname statement using it.

We used this approach for testing in our project without any problem.


Here some code:

<?php

/**
 * Bootstrap file for (re)creating database before running tests
 *
 * You only need to put this file in "bootstrap" directory of the project
 * and change "bootstrap" phpunit parameter within "phpunit.xml"
 * from "bootstrap/autoload.php" to "bootstap/testing.php"
 */

$testEnvironment = 'testing';

$config = require("app/config/{$testEnvironment}/database.php");

extract($config['connections'][$config['default']]);

$connection = new PDO("{$driver}:user={$username} password={$password}");
$connection->query("DROP DATABASE IF EXISTS ".$database);
$connection->query("CREATE DATABASE ".$database);

require_once('app/libraries/helpers.php');

// run migrations for packages
foreach(glob('vendor/*/*', GLOB_ONLYDIR) as $package) {
    $packageName = substr($package, 7); // drop "vendor" prefix
    passthru("./artisan migrate --package={$packageName} --env={$testEnvironment}");
}
passthru('./artisan migrate --env='.$testEnvironment);

require('autoload.php'); // run laravel's original bootstap file
like image 52
neoascetic Avatar answered Nov 15 '22 16:11

neoascetic


neoascetic has the best answer because essentially you have to boot laravel's database config file again.

So, a clever hack is to create database again after you have dropped it. No need to touch config/database.

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

    Artisan::call('migrate');
    $this->seed();
    Mail::pretend(true);
}

public function tearDown() {
    parent::tearDown();

    DB::statement('drop database coretest;');
    DB::statement('create database coretest;');
}
like image 33
Ryan Boyd Avatar answered Nov 15 '22 16:11

Ryan Boyd