Max13's avatar
Level 3

Create a test DB during testing (no migration)

Hi,

I'm testing a repository I'm writing, and I'd like to create a test DB (in memory) to make some tests.

Basically, I would like to create a Schema which would be migrated in my test constructor, for instance:

Schema::create('empty_test_models', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->timestamps();
});

Currently, here is the error: Fatal error: Uncaught Error: Call to a member function connection() on null. Maybe it's not the right way, is there a way other than a raw statement?

0 likes
9 replies
bobbybouwmann's avatar

You can run raw statements using DB::statement('your query here');. However I don't think that is what you need. When you run your tests Laravel will read out the phpunit.xml file. If you want you can you can configure an in memory database there and use that in your tests! As long as you migrate the database during your test of course!

Laracasts video: https://laracasts.com/series/whats-new-in-laravel-5-5/episodes/14

The video will you explain what happens underwater, but in the end you just need to set this variable in that phpunit.xml file

<env name="DB_DATABASE" value=":memory:"/>
Max13's avatar
Level 3

As long as you migrate the database during your test of course!

Actually, as I wrote, I want to create a particular migration for some of my tests, not using my production migrations.

I tried to set in my test constructor a Schema, only to migrate a test table, but I don't understand the issue.

The phpunit.xml has DB_CONNECTION and DB_DATABASE already set:

<php>
    <env name="APP_ENV" value="testing"/>
    <env name="BCRYPT_ROUNDS" value="4"/>
    <env name="CACHE_DRIVER" value="array"/>
    <env name="DB_CONNECTION" value="sqlite"/>
    <env name="DB_DATABASE" value=":memory:"/>
    <env name="SESSION_DRIVER" value="array"/>
    <env name="QUEUE_DRIVER" value="sync"/>
    <env name="MAIL_DRIVER" value="array"/>
</php>
bobbybouwmann's avatar

@Max13 Why would you want to create a separate migration for your tests? Your tests should test things in the real world right? How much value does a test add if the test database is different from your production database?

Max13's avatar
Level 3

@bobbybouwmann Short answer, no offense, simply because I want.

Long answer: As I introduced, I'm writing a repository (and an abstract base class) and I'm trying to write some tests. Tests should test units (or small portions) of my app, and while my base repo test tests the interactions between the repo and the underlying builder, I'd also like to test (on a simple dummy in-memory table) that the base repo will return expected results.

In this case, I don't need to test real world interactions, but rather an expected behavior no matter the table/model structure. Which lead me to create a dummy table (see Schema in my first post).

bobbybouwmann's avatar

I would probably fake the response from the repository instead of using a single migration to run your tests. Anyway, it's up to you ;)

Max13's avatar
Level 3

Well... faking the repository response won’t allow me to test response types and structures as they will be faked ?

Anyway, it’s not a bad suggestion, but still, I don’t have a clue about how to create a table using Schema builder in the tests ?

Don’t you have one?

bobbybouwmann's avatar
Level 88

You can create a separate directory where you store the migrations for your tests. Then you simply run the artisan command in your tests specifying the location of the migration.

Artisan::call('migrate', ['--path' => base_path('tests/migrations')]);
1 like
Max13's avatar
Level 3

I didn’t think about that. Great idea, thank you!

Please or to participate in this conversation.