A PHPUnit extension that enables tests to run inside Swoole coroutines, specifically designed for testing Hyperf applications and other Swoole-based frameworks.
composer require friendsofhyperf/co-phpunit --devWhen testing Hyperf applications, many components rely on Swoole's coroutine context to function properly. Running tests in a traditional synchronous environment can lead to issues such as:
- Coroutine context not being available
- Timers and event loops not working correctly
- Coordinator pattern failures
- Database connection pool issues
Co-PHPUnit solves these problems by automatically wrapping test execution in a Swoole coroutine context when needed.
Simply use the RunTestsInCoroutine trait in your test class:
<?php
namespace Your\Namespace\Tests;
use FriendsOfHyperf\CoPHPUnit\Concerns\RunTestsInCoroutine;
use PHPUnit\Framework\TestCase;
class YourTest extends TestCase
{
use RunTestsInCoroutine;
public function testSomething()
{
// Your test code here
// This will automatically run inside a Swoole coroutine
}
}If you need to disable coroutine execution for a specific test class, set the $enableCoroutine property to false:
<?php
namespace Your\Namespace\Tests;
use FriendsOfHyperf\CoPHPUnit\Concerns\RunTestsInCoroutine;
use PHPUnit\Framework\TestCase;
class YourTest extends TestCase
{
use RunTestsInCoroutine;
protected bool $enableCoroutine = false;
public function testSomething()
{
// This test will run in normal synchronous mode
}
}The RunTestsInCoroutine trait overrides PHPUnit's runBare() method to:
- Check Prerequisites: Verifies that the Swoole extension is loaded and not already in a coroutine context
- Create Coroutine Context: Wraps test execution in
Swoole\Coroutine\run() - Exception Handling: Properly captures and re-throws exceptions from within the coroutine
- Cleanup: Clears all timers and resumes coordinator on test completion
- Fallback: If conditions aren't met, falls back to normal test execution
The package includes a phpunit-patch.php file that automatically removes the final keyword from PHPUnit's TestCase::runBare() method, allowing the trait to override it. This patch is applied automatically when the package is autoloaded.
- PHP >= 8.0
- PHPUnit >= 10.0
- Swoole extension (when running tests in coroutine mode)
- Hyperf >= 3.1 (for coordinator functionality)
The package automatically registers its autoload files in composer.json:
{
"autoload-dev": {
"psr-4": {
"Your\\Tests\\": "tests/"
},
"files": [
"vendor/friendsofhyperf/co-phpunit/phpunit-patch.php"
]
}
}No special PHPUnit configuration is required. The package works seamlessly with your existing phpunit.xml configuration.
- Use for Integration Tests: This is particularly useful for integration tests that interact with Hyperf's coroutine-aware components
- Selective Enablement: Not all tests need to run in coroutines. Use
$enableCoroutine = falsefor unit tests that don't require coroutine context - Test Isolation: The package automatically cleans up timers and coordinator state between tests
- Performance: Tests running in coroutines may have slightly different performance characteristics
<?php
namespace App\Tests;
use FriendsOfHyperf\CoPHPUnit\Concerns\RunTestsInCoroutine;
use Hyperf\Context\ApplicationContext;
use PHPUnit\Framework\TestCase;
class ServiceTest extends TestCase
{
use RunTestsInCoroutine;
public function testServiceWithCoroutineContext()
{
// Get service from container
$service = ApplicationContext::getContainer()->get(YourService::class);
// Test methods that use coroutine context
$result = $service->asyncOperation();
$this->assertNotNull($result);
}
public function testDatabaseConnection()
{
// Test database operations that require connection pool
$result = Db::table('users')->first();
$this->assertIsArray($result);
}
}If tests hang, ensure that:
- All async operations are properly awaited
- No infinite loops exist in coroutine callbacks
- Timers are cleared in test teardown
This usually indicates that coroutine context is not available. Ensure:
- Swoole extension is installed and enabled
- The
RunTestsInCoroutinetrait is included $enableCoroutineis set totrue
The package supports PHPUnit 10.x, 11.x, and 12.x. Ensure your PHPUnit version is compatible.
Contributions are welcome! Please feel free to submit a Pull Request.
- Issues: GitHub Issues
- Documentation: Hyperf Fans
- Pull Requests: GitHub Pull Requests
This package is open-sourced software licensed under the MIT license.