17

My unit tests recently started failing. I am getting this error:

PDOException: SQLSTATE[HY000]: 
General error: 1 table loan_details has no column named start_month

The line where it is happening, I have this code:

$loan = LoanDetails::create(['loan_percentage' => .8,
        'loan_product_id' => 1,
        'interest_rate' => .5,
        'start_month' => 0,
        'term' => 120,
        'fixed_finance_fee' => 0,
        'variable_finance_Fee' => 0,
        'valid_from' => '2015-01-01'
    ]);

If I comment out the "start_month" line then it logically works.

In the setup of my unit tests I run all migrations (about 80).

I have a migration that looks like this:

Schema::table('loan_details', function(Blueprint $table){
     $table->integer('start_month')->unsigned()->after('interest_only')->default(0);
     $table->decimal('balloon_percent',4,3)->after('term')->nullable();
     $table->integer('balloon_month')->after('balloon_percent')->nullable();
     $table->dropColumn('ordinal_rank');
});

So, I wondered if all the migrations weren't running so I ran this code:

$rows = DB::table('migrations')->get();
print_r($rows);

This lists all of the migrations as having completed. I am using an in memory sqlite db for the tests.

I am wondering if the migrations are run asynchronously and they aren't all finished by the time my code runs? Or if the migrations are silently failing somewhere?

I've been at this for hours and don't know what is happening.

*UPDATE I have a migration that runs AFTER the above migration, and I confirmed that the subsequent migration was successful. So it is just this one migration that is silently failing in some way.

ajon
  • 7,868
  • 11
  • 48
  • 86

2 Answers2

47

I found the issue. It is because of the ridiculous limitation that sqlite has of not having multiple add column statements in one table call as seen here.

When I separate out the migration as below it works:

Schema::table('loan_details', function(Blueprint $table){
    $table->integer('start_month')->unsigned()->after('interest_only')->default(0);
});
Schema::table('loan_details', function(Blueprint $table){
    $table->decimal('balloon_percent',4,3)->after('term')->nullable();
});
Schema::table('loan_details', function(Blueprint $table){
    $table->integer('balloon_month')->after('balloon_percent')->nullable();
});
Schema::table('loan_details', function(Blueprint $table){
    $table->dropColumn('ordinal_rank');
});
ajon
  • 7,868
  • 11
  • 48
  • 86
  • 1
    Thanks for the answer. This helped a great deal. It is very disappointing that you cannot use $table->morphs('taggable'); since this creates to columns and an index which will be problematic when unit testing with sqlite. – Hendrik Jan 30 '18 at 10:11
  • Thanks for this. This really helps and works for me. – Jur P Sep 06 '19 at 05:13
  • 1
    I could make tests to check the schema is even correct but it seems ridiculous. $this->assertTrue(Schema::hasColumn('users', 'firstName'), 'Users table does not have a firstName column.'); $this->assertTrue(Schema::hasColumn('users', 'lastName'), 'Users table does not have a lastName column.'); I can see the sqlite schema by doing this from a test. dd(DB::select("SELECT name, sql FROM sqlite_master WHERE type='table' ORDER BY name;")); – Liam Mitchell May 07 '21 at 01:09
2

To check SQLite DB records here

There are many other useful built-in dot commands -- see the documentation at http://www.sqlite.org/sqlite.html, section Special commands to sqlite3.

also, check DB schema

Ajay
  • 848
  • 8
  • 17