herrera-io/phpunit-test-case
PHPUnit TestCase class and Extras trait that add helpers for common test chores: create/delete temporary files and directories, call protected/private methods, and get/set protected/private properties. Use as a base class or mix into your own test case.
Installation:
composer require herrera-io/phpunit-test-case=1.*
(Note: Requires PHPUnit 3.7.x—ensure your project’s phpunit/phpunit dependency is pinned to ^3.7 in composer.json.)
Basic Setup:
Choose either the TestCase class or the Extras trait (not both):
// Option 1: Extend TestCase
use Herrera\PHPUnit\TestCase;
class UserTest extends TestCase
{
// Tests...
}
// Option 2: Use Extras trait (with PHPUnit_Framework_TestCase)
use Herrera\PHPUnit\Extras;
class UserTest extends \PHPUnit_Framework_TestCase
{
use Extras;
}
First Use Case: Test a protected method in a Laravel model:
public function testProtectedValidation()
{
$user = new User(['email' => 'test@example.com']);
$result = $this->callProtectedMethod('validateOnly', ['email'], $user);
$this->assertTrue($result);
}
Service Container Testing:
Use callPrivateMethod() to test private container bindings:
public function testPrivateBinding()
{
$service = $this->callPrivateMethod('resolve', ['MyService'], $this->app);
$this->assertInstanceOf(MyService::class, $service);
}
Artisan Command Logic: Access protected command methods:
public function testCommandLogic()
{
$command = new MyCommand();
$output = $this->callPrivateMethod('execute', [], $command);
$this->assertContains('Success', $output);
}
File-Based Tests:
Combine with Laravel’s Storage facade for temp files:
public function testFileUpload()
{
$tempFile = $this->createTempFile('upload', 'txt');
Storage::fake('local')->put('test.txt', 'content');
$this->assertTrue(file_exists($tempFile));
}
Trait Composition:
Use alongside Laravel’s TestCase for hybrid testing:
use Herrera\PHPUnit\Extras;
use Illuminate\Foundation\Testing\TestCase as LaravelTestCase;
class MyTest extends LaravelTestCase
{
use Extras;
protected function tearDown(): void
{
parent::tearDown(); // Laravel's tearDown
$this->cleanupExtras(); // Extras' cleanup
}
}
Database + Temp Files:
Pair with refreshDatabase() for atomic tests:
public function testFileUploadWithDB()
{
$this->refreshDatabase();
$tempDir = $this->createTempDir();
// Test logic...
$this->assertDatabaseHas('uploads', ['path' => $tempDir]);
}
PHPUnit 3.7 Lock-In:
Class 'PHPUnit_Framework_TestCase' not found if using PHPUnit 8+.phpunit/phpunit:^3.7 in composer.json or fork the package.TearDown Hell:
parent::tearDown() causes temp files to persist.tearDown() and chain calls:
protected function tearDown(): void
{
$this->cleanupExtras(); // Extras' cleanup
parent::tearDown(); // Laravel/PHPUnit cleanup
}
Reflection Warnings:
callPrivateMethod() may trigger E_STRICT warnings in PHP 7+.@$this->callPrivateMethod('method', [$arg], $object);
Symfony/Process Deprecations:
symfony/process:2.1 may fail on modern OSes (e.g., macOS).symfony/process:^6.0.Temp File Leaks:
$this->getTempDir() to list remaining temp files.dd($this->getTempFiles()) to debug cleanup.Private Method Failures:
get_class_methods($object) to list available methods.Custom Cleanup:
Override cleanupExtras() to add logic:
protected function cleanupExtras(): void
{
parent::cleanupExtras();
// Custom cleanup (e.g., delete logs)
}
Temp File Naming:
Extend createTempFile()/createTempDir() for custom prefixes:
$this->createTempFile('laravel_', 'log');
Laravel-Specific Helpers: Add static methods to the trait for Laravel use cases:
// In Extras.php (forked)
public static function callPrivateServiceMethod(string $method, array $args, $service)
{
return static::callPrivateMethod($method, $args, app($service));
}
How can I help you explore Laravel packages today?