Dimitrios Desyllas
Dimitrios Desyllas

Reputation: 10134

How I can have on each phpunit test specific tearDown logic?

On my phpunit tests I need to run a cleanup functionality for each test seperately for example:

use PHPUnit\Framework\TestCase;

use MyApp\Database\DatabaseEntryDataGenerator;
use MyApp\Database\Record\User;
use MyApp\Database\Record\Emails;

class MyEmailTest extends TestCase
{

   public function testEmailValid()
   {
     /**
      * @var EmailEntries
      */
     $emails=DatabaseEntryDataGenerator::table(EmailEntries::TABLE)->generate();

     //Do test
    $emails->delete();
   }

   public function testEmailValidOnUser()
   {
     /**
      * @var User
      */
     $user=DatabaseEntryDataGenerator::table(User::TABLE)->generateSingle(1);
     /**
      * @var EmailEntries
      */
     $emails=DatabaseEntryDataGenerator::table(EmailEntries::TABLE)->generateMultiple();

     //Do test
    $emails->delete();
    $user->delete();
   }
}

Assume that fictional DatabaseEntryDataGenerator generates data on database and the fictional EmailEntries and User represent the record data. The method delete on EmailEntries and User.

But if during the development of the test something brak mucase the delete that is the cleanup code may be deleted. Also the generic tearDown is way to generid and does not allow to specify a specific method indicain a test the required tearDown logic. For example in my case the teardown logic on testEmailValid id Different on testEmailValidOnUser and if something breakd for example due to a typo, may end up not be able to run it aall hence not giving me the test isolation.

So how I can have per-test specific tear down logic that will be executed regardless the test is successfull or not?

Upvotes: 0

Views: 328

Answers (2)

Bryan
Bryan

Reputation: 3494

I would suggest using database transaction here. You really want to do the same thing in both tests: rollback any changes made to the database.

public function setUp(): void
{
    MyDatabaseClass:startTransaction();
}

public function tearDown(): void
{
    MyDatabaseClass:rollback();
}

This way you won't need to have special logic for each test, and if you are affecting more tables than expected, you will still be safe.

Upvotes: 0

Ghlen
Ghlen

Reputation: 659

The only way to do this is by using seperate classes. If you are in need of different teardown logic per test, you are either having architectural issues, are testing different functionality or simply don't have a good enough teardown strategy.

Often times, simple truncate logic will suffice during the teardown logic.

Upvotes: 1

Related Questions