30 Days of Automated Testing:Using PHPUnit【D14】

setUp(), tearDown(), and Data Provider

WilliamP
3 min readJan 29, 2023

Today, we will introduce several special functions that can be used when writing test code.

setUp() & tearDown()

  • setUp():We can use this function to write any logic that we want to execute before each test case function runs.
  • tearDown():We can write the logic that we want to run after each test case function in this function.
  • Example:
<?php

namespace Tests\Unit;

use App\Services\TestService;
use PHPUnit\Framework\TestCase;

class TestServiceTest extends TestCase
{
private $service;

public function setUp(): void
{
$this->service = app(TestService::class);
parent::setUp();
}

public function testCanCalcuateBmi()
{
$bmiActual = $this->service->calculateBmi(1.6, 64.0);
$bmiExpected = 64.0/(1.6*1.6);

$this->assertEquals($bmiExpected, $bmiActual);
}

public function tearDown(): void
{
parent::tearDown();
$this->service = null;
}
}

In the above code, setUp() is called before each test case function is executed, initializing $this->service; tearDown() is called after each test case function is executed, cleaning up $this->service.

setUpBeforeClass() & tearDownAfterClass()

  • setUpBeforeClass():Similar to setUp(), but it will only be executed before the first test case function of each test class is executed.
  • tearDownAfterClass():Similar to tearDown(), but it will only be executed after the first test case function in each test class is executed.
  • Example:
<?php

namespace Tests\Unit;

use App\Services\TestService;
use PHPUnit\Framework\TestCase;

class TestServiceTest extends TestCase
{
private $service;
private static $flag;

public static function setUpBeforeClass(): void
{
self::$flag = true;
parent::setUpBeforeClass();
}

public function setUp(): void
{
$this->service = app(TestService::class);
parent::setUp();
}

public function testCanThrowExceptionWhenInvaliHeight()
{
$this->expectException(Exception::class);
$this->service->calculateBmi(0.0, 1.0);
}

public function testCanThrowExceptionWhenInvaliWeight()
{
$this->expectException(Exception::class);
$this->service->calculateBmi(1.0, 0.0);
}

public function testCanThrowExceptionWithMessageWhenInvaliData()
{
$this->expectExceptionMessage('Invalid');
$this->service->calculateBmi(0.0, 1.0);
}

public function testCanThrowExceptionWithMessageRegexMatcchWhenInvaliData()
{
$this->expectExceptionMessageMatches('/Invalid/');
$this->service->calculateBmi(0.0, 1.0);
}

public function testCanThrowExceptionWithCodeWhenInvaliData()
{
$this->expectExceptionCode(1);
$this->service->calculateBmi(0.0, 1.0);
}

public function tearDown(): void
{
parent::tearDownAfterClass();
$this->service = null;
}

public static function tearDownAfterClass(): void
{
self::$flag = false;
parent::tearDownAfterClass();
}
}

Special attention should be paid that setUpBeforeClass() and tearDownAfterClass()can only be declared as static functions.

Data Providers

Now, let’s move on to the main event of today. This feature is similar to the @testWith that was introduced yesterday. Without further ado, let's take a look at an example!

  • Example
<?php

namespace Tests\Unit;

use App\Services\TestService;
use Exception;
use PHPUnit\Framework\TestCase;

class TestServiceTest extends TestCase
{
/**
* @dataProvider bmiProvider
*/
public function testCanThrowException(float $height, float $weight)
{
$service = app(TestService::class);
$this->expectException(Exception::class);
$service->calculateBmi($height, $weight);
}

public function bmiProvider()
{
return [
[1.0, 0.0],
[0.0, 1.0],
[0.0, 0.0],
];
}
}

In the above code, we have created a Data Provider function, bmiProvider(), and a test case function, testCanThrowException(), and have marked it to use the bmiProvider() Data Provider function. In this test class, testCanThrowException() will actually be executed 3 times, respectively:

  • testCanThrowException(1.0, 0.0)
  • testCanThrowException(0.0, 1.0)
  • testCanThrowException(0.0, 0.0)

Actually, its usage is very similar to the @testWith from the previous day, but it's more intuitive and more similar to writing test programs.

That concludes today’s introduction!

Next time, let’s take a look at Seeder.

If you liked this article or found it helpful, feel free to give it some claps and follow the author!

Reference

--

--