I have an artisan command (Laravel 10) that makes a change to the user table in the database. I can confirm that the change is happening with output from the command itself, and it looks like it's actually working.
However, when I run the unit test, it does not see the updated database change.
Unit Test
public function test_promote_user_command_sets_user_as_super_admin()
{
$user = $this->createUser('guest');
$response = $this->artisan("user:promote {$user->email}")->assertSuccessful();
$role = Role::where('name', '=', 'Super Admin')->first();
$this->assertDatabaseHas('users', [
'id' => $user->id,
'role_id' => $role->id
]);
}
Artisan Command
class PromoteUserCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'user:promote {email}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Promote a user to super admin.';
/**
* Execute the console command.
*/
public function handle(): void
{
$role = Role::where('name', '=', 'Super Admin')->first();
$user = User::where('email', '=', $this->argument('email'))->first();
$user->role_id = $role->id;
$user->save();
}
}
When I run the test I get this output:
Failed asserting that a row in the table [users] matches the attributes {
"id": 1,
"role_id": 1
}.
Found similar results: [
{
"id": 1,
"role_id": null
}
].
However, if in the artisan command I run dd($user) after the $user->save() and then I run the test, I get this:
...
#attributes: array:9 [
"id" => 1
"name" => "Karelle Schamberger"
"email" => "[email protected]"
"email_verified_at" => "2023-03-04 18:22:36"
"password" => "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi"
"remember_token" => "Br992xsWw9"
"created_at" => "2023-03-04 18:22:36"
"updated_at" => "2023-03-04 18:22:36"
"role_id" => 1
]
#original: array:9 [
"id" => 1
"name" => "Karelle Schamberger"
"email" => "[email protected]"
"email_verified_at" => "2023-03-04 18:22:36"
"password" => "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi"
"remember_token" => "Br992xsWw9"
"created_at" => "2023-03-04 18:22:36"
"updated_at" => "2023-03-04 18:22:36"
"role_id" => 1
]
#changes: array:1 [
"role_id" => 1
]
...
So I know that the command is being run and that it is working properly. Why does it seem that this change is reverted before the test assertion happens?
Edited to add:
I also changed the command to do a DB lookup on the table after the $user->save() and the DB result also shows the change is in the database...
So the DB changes is taking place within the artisan command, but either that change is reverted or some how the unit test is not seeing the latest DB status.
All of my other 94+ tests that do not involve the artisan command work just fine with database testing. It is only the artisan command that is having this issue.