Arrange, act, assert only works if the previous test left no rows behind. Each test needs an empty database. A row left behind by the previous test makes the next one fail for a reason that has nothing to do with the invoice. RefreshDatabase migrates the testing database once, then rolls each test back.
Test-driven Laravel · Lesson 1
Refreshing the database
Video
01 Point the tests at their own database
Use the trait from the Pest file, or on the test class. The connection is the one in phpunit.xml, not the database the site is serving.
uses(RefreshDatabase::class);
it('starts from an empty invoices table', function () {
expect(Invoice::query()->count())->toBe(0);
Invoice::factory()->create();
expect(Invoice::query()->count())->toBe(1);
});The invoice from this test is gone when the next test starts. That is the transaction rolling back, so do not expect a job process outside the test to see the row: it was never committed. A test that must commit uses a different path. This series does not need one.
Never aim RefreshDatabase at the database you use in the browser. Migrate and roll back belong to the testing database only.
02 The testing connection is a different database
phpunit.xml, or the Pest environment, points DB_DATABASE at a database that exists only for the suite. The site’s database keeps its rows. A test that creates an invoice writes to the testing database, and the transaction rolls that write back before the next test.
<env name="DB_DATABASE" value="laravel_testing"/>If a test seems to see a row it did not create, it is either missing the trait or it is connected to the database you browse. Check the connection inside the test before you start deleting rows by hand. An outside process, including a queue worker started in another terminal, will not see the invoice either: the test never committed it.
DatabaseMigrations rebuilds the schema for every test. RefreshDatabase migrates once and wraps each test in a transaction. Prefer the transaction. A suite that migrates from scratch each time is slower and no cleaner, because the rollback already gives the next test an empty invoices table.
Recap
You can give each test an empty database without touching the one the browser uses.
RefreshDatabasemigrates the testing database, then rolls each test back.- A worker outside the test cannot see the invoice, because it was never committed.
- If a test sees a row it did not create, it is missing the trait or it is on the wrong database.
Check yourself · 3 questions
Question 1 of 3A queue worker you started in another terminal does not see the invoice the test created. Why?