Ad

What Would Cause User::destroy($id) To Actually Delete The Entry In This Case?

- 1 answer

As a tester, I want to feel more secure by having each test start with a fresh database (one starting entry).

With Laravel and PHPUnit, you can do this with the RefreshDatabase trait. This stopped working for my latest test.

I then tried MyModel::destroy($id). This also didn't destroy the new entries.

How do I destroy the brain of these zombie entries?

I have:

  • a table called "users" with one user
  • a model called User
  • a test for activating deactivating users
  • use of the RefreshDatabase trait
  • PHPUnit using SQLite in :memory:
  • Laravel 6.5.2

Here's my test; I've commented about the problem.

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Models\User;
use Tests\TestCase;

class UsersTest extends TestCase
{
    use RefreshDatabase;

    /**
     * Activate user test
     * 
     * @test
     * @return void
     */
    public function asAdminActivateUser()
    {

        // (Test code)

        $user = factory(User::class)->create();

        // Prove the newly gen'd user has the id: 2.
        assert(User::find(2)->name === $user->name, "The factory gen an entry with a diff id");

        // (More test code)

        // In a following test, the db still had two users (should be one), so I used this
        User::destroy(2);

        // This fails
        assert(User::all()->count() === 1, "The destroy method didn't work!");

    }
}

I've tried:

  • use RefreshDatabase;
  • User::find(2)->delete();
  • use DatabaseMigrations;
  • some long script that works directly with DB;
  • User::destroy([2]);

What's the cause of User::destroy(2) not destroying something? What can I do to make it destroy the entry?

Ad

Answer

First, there's a use DatabaseTransactions; Trait that you may want to look at because I believe that there have been documented performance reasons for why RefreshDatabase does not reset the auto-increment value after each test.

As for your questions, as you mentioned this would be the correct syntax User::find(2)->delete(), if you were certain that you were actually working with a user with an id of 2, however, because of what I mentioned earlier the tables auto-incrementing id column is likely past 2 because of other tests you have already run up to that point.

As your proof is hypothetical and likely does not reflect the actual implementation that you are actually facing in the real code, what can choose to remove the user yourself after you have run your assertions against the user:

...
// (Test code)

$user = factory(User::class)->create();

// Prove the newly gen'd user has the id: 2.
assert(User::find(2)->name === $user->name, "The factory gen an entry with a diff id");
$user->delete();
...

An alternative would be to clean up your database manually with User::orderByDesc('id')->take(1)->delete() or User::skip(1)->delete() to return your database to having one User.

Ad
source: stackoverflow.com
Ad