ahamilton9
ahamilton9

Reputation: 164

Laravel Schema::create ignoring table prefix when run from Unit Test

I have a unit test that is running a seeder I've constructed to create a new instance of one of my classes. When I run the seeder from Artisan, it runs without issue. However, when the unit test does it:

class MyClassTest extends TestCase {
    public function setUp() {
        // Setup application
        parent::setUp();

        $this->seed('MyClassSeeder');
    }

... the following bit that gets run refuses to use the prefix!

class MyClass extends Base {
    // Switch to the proper DB prefix
    protected function prefix() {
        DB::connection('main')->setTablePrefix($this->id . '_');
        return $this;
    }

    // This is run by the seeder, everything up to here works fine...
    public function setupDatabase() {
        $this->prefix();

        // This returns "1001_", which is correct
        Log::info(Schema::connection('main')->getConnection()->getTablePrefix());

        // Creates "myTable" instead of "1001_myTable"
        if(!Schema::connection('main')->hasTable('myTable')) {
             Schema::connection('main')->create('myTable', function($table) {
             ...

As it works fine when I run it manually, I'm not even sure where to start looking. It's even returning the proper prefix, just not using it. Has anyone else seen this? Is it reproducible? Is the testing environment (automatically used by unit tests) turning something off other than the filters, which I've already re-enabled?

Any help would be appreciated. Even a reproduction would at least tell me it's not our code. We've extended quite a bit, but there should be no major changes to the Laravel codebase on our install.

FURTHER TESTING

So I continued my testing, and found what appears to be a bug, though I'm going to look into it further, I'm posting it here in case it jogs anyone's memory for a similar issue:

I modified

Log::info(Schema::connection('main')->getConnection()->getTablePrefix());

to be

Log::info('Grammar Prefix: ' . Schema::connection('promotion')->getConnection()->getSchemaGrammar()->getTablePrefix());
Log::info('Connection Prefix: ' . Schema::connection('promotion')->getConnection()->getTablePrefix());

And found that while the Connection Prefix line works properly as it did before, the Grammar's Prefix is non-existent. The Grammar and Connection prefixes don't match. While I can work around this, I'd like to know why it's held consistent when I run it in any way other than through the unit testing class, but there's a mismatch here. Will be reporting as a bug soon if it appears that way to anyone else.

FINAL TESTING

From what I can tell, the code should get the initial settings from it's database config file, and then both the Blueprint and Schema should use the updated prefix when the line

DB::connection('promotion')->setTablePrefix($this->id . '_');

is run. I've worked around it by also running the line

DB::connection('promotion')->getSchemaGrammar()->setTablePrefix($this->id . '_');

Which seems to fix the issue. This shouldn't be necessary, and I see no reason the code I'm using should not have the desired effect. I'm considering this a bug, and will report it later today. I'll leave the question open for a bit in case I'm missing something, but I'll close it soon.

Upvotes: 4

Views: 1299

Answers (2)

ahamilton9
ahamilton9

Reputation: 164

I've come to the conclusion this is a bug. There's no explanation why it would work in one environment but not the other unless Testing is doing something different than a default environment, and I can't find it.

Upvotes: 2

Paul Bele
Paul Bele

Reputation: 1534

PHPUnit doesn't change anything to how Laravel interacts with the database. Make sure that your configuration is not overridden when you run tests by any environment configuration

Also make sure you are setting and using the same connection . In the code you provided, you are setting up the prefix for connection promotion, yet you are using connection main Here is an example that works, i tried to make it as similar as yours.

TestSeedTest.php

<?php

class TestSeedTest extends TestCase{

   public function setUp() {
        // Setup application
        parent::setUp();


    }

    public function testSeeder(){

        $this->seed('MyClassSeeder');

    }

}
?>

MyClassSeeder.php

<?php

class MyClassSeeder extends Seeder {

    private $id='123';

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $this->setupDatabase();

    }

    protected function prefix() {

        DB::connection('promotion')->setTablePrefix($this->id . '_');

        return $this;
    }


    // This is run by the seeder, everything up to here works fine...
    public function setupDatabase() {
        $this->prefix();


        if(!Schema::connection('promotion')->hasTable('myTable')) {
             Schema::connection('promotion')->create('myTable', function($table) {

                $table->increments('id');
                $table->string('test');
                $table->timestamps();
            });
        }

    }

}

Upvotes: 0

Related Questions