I'm trying to test an artisan
command that is designed to do some database maintenance.
In particular, it searches for records that don't have a column filled, and fill it.
This is a simplified version of the fire()
method of the command:
public function fire()
{
$items = Item::all();
$total = $items->count();
$updated = 0;
foreach ($items as $item) {
if ($item->myColumn != 'x') {
$item->myColumn = 'x';
$item->save();
$updated++;
}
}
$this->info("total: $total updated: $updated");
}
My (acceptance) test is very simple and does the following:
artisan
commandThis is the code:
public function doTheTest(AcceptanceTester $I)
{
$I->wantTo('setup the myColumn when it is not set');
$id = $I->haveRecord('items', [
'myColumn' => '',
]);
$I->runShellCommand('php artisan items:updater');
$I->seeRecord('items', [
'id' => $id,
'myColumn' => 'x',
]);
}
However the test fails, and I get the following message:
Couldn't see record "items",{"id":101,"myColumn":"x"}:
Couldn't find items with {"id":101,"code":"x"}
As you can see, the id
of the new record is 101, because there are already 100 items in the db dump, but what it is strange is that the $this->info()
in the command prints
total: 100 updated: 100
as if the database used inside the test and the one used inside artisan
are different.
Moreover, if at the end of the test I try to grab the added record, and print it, as shown in the following snippet
public function doTheTest(AcceptanceTester $I)
{
/* ... */
$item = $I->grabRecord('items', [
'id' => $id,
]);
\Codeception\Util\Debug::debug($item);
}
and run the codecept run acceptance --debug
command, I get the added record
stdClass Object
(
[id] => 101
[myColumn] =>
)
I'm very confused, because the there is a single database, but I'm surely misunderstanding something important here.
Could anyone give me a help?
Thank you very much,
The issue is that every query using Laravel4 module is run in a transaction that, by default, will be rolled back at the end. If you take a look at the Config section of Laravel4 documentation it states
cleanup: boolean, default true - all db queries will be run in transaction, which will be rolled back at the end of test.
You can check this if you restart the MySQL server (in which case, when you run the tests again you'll still see the id 101), or take a look at MySQL logs that will have an entry like the following for each test:
150417 23:24:24 2 Connect root@localhost on laravel-test
2 Prepare set names 'utf8' collate 'utf8_unicode_ci'
2 Execute set names 'utf8' collate 'utf8_unicode_ci'
2 Close stmt
2 Query START TRANSACTION
2 Prepare insert intoitems
(myColumn
) values (?)
2 Execute insert intoitems
(myColumn
) values ('')
2 Close stmt
2 Query ROLLBACK
2 Quit
To fix this, you need to configure the option cleanup
of Laravel4 module in your codeception.yml
file, like this:
modules:
config:
Laravel4:
cleanup: false