VOOZH about

URL: https://deepwiki.com/hypervel/testbench/9-advanced-topics

⇱ Advanced Topics | hypervel/testbench | DeepWiki


Loading...
Last indexed: 7 February 2026 (93289f)
Menu

Advanced Topics

This page covers advanced usage patterns, extension mechanisms, and troubleshooting techniques for complex testing scenarios in the Hypervel Testbench. These topics are intended for users who need to go beyond basic test writing and require fine-grained control over the test environment, asynchronous operations, or custom testing infrastructure.

Scope: This page provides an overview of advanced concepts. For detailed information on specific topics, see:

For basic test writing, see Quick Start Guide. For configuration management, see Configuration Management.


Extension Points and Customization

The TestCase class provides multiple extension points through protected methods and callbacks that allow customization of application setup, routing, database configuration, and test lifecycle.

Application Lifecycle Callbacks

The testbench provides two primary callback mechanisms for application lifecycle management: afterApplicationCreated() and beforeApplicationDestroyed() (via parent class). These callbacks execute during specific phases of the test lifecycle.


Diagram: Application Lifecycle and Callback Execution Flow

The callback registered in src/TestCase.php45-51 performs three critical operations:

  1. Timer::clearAll() - Clears any Swoole timers from previous tests
  2. CoordinatorManager::until(Constants::WORKER_EXIT)->resume() - Resets the worker exit coordinator
  3. setUpApplicationRoutes() - Configures routes after providers are booted

Sources: src/TestCase.php38-58

Override Points for Test Customization

The following table summarizes the primary extension points available in TestCase:

MethodPurposeCall SiteTypical Use Case
defineEnvironment(ApplicationContract $app)Register providers and aliasessrc/TestCase.php63-67Add package-specific service providers
defineRoutes(Router $router)Define general routessrc/Concerns/HandlesRoutes.php19-22Register API or utility routes
defineWebRoutes(Router $router)Define web middleware routessrc/Concerns/HandlesRoutes.php27-30Register routes requiring CSRF, session
defineDatabaseMigrations()Setup database schemaVia HandlesDatabases traitSpecify test database migrations
createApplication()Create application instancesrc/TestCase.php69-78Customize application container bindings
afterApplicationCreated(Closure $callback)Post-creation hooksrc/TestCase.php45Perform setup after app is fully booted

Sources: src/TestCase.php38-110 src/Concerns/HandlesRoutes.php1-48

Method Override Pattern

The HandlesRoutes trait demonstrates the pattern used for conditional method execution. The defineWebRoutes() method only executes if overridden in a child class:


Diagram: Conditional Route Setup Using Reflection

This pattern at src/Concerns/HandlesRoutes.php43-44 uses ReflectionMethod to check if defineWebRoutes() was overridden. If not, it skips the empty web route group registration, preventing interference with other routes.

Sources: src/Concerns/HandlesRoutes.php35-47


Application Lifecycle Management

Application Reloading

The reloadApplication() method provides a way to reset the application state within a single test method. This is useful when testing behavior that depends on fresh application state or when testing bootstrap logic multiple times.


Diagram: Application Reload Process

The implementation at src/TestCase.php93-97 simply calls tearDown() followed by setUp(), ensuring complete cleanup and re-initialization. This is particularly useful for testing:

  • Different environment configurations in a single test
  • Bootstrap behavior under various conditions
  • Service provider registration order dependencies

Sources: src/TestCase.php80-97

Bootstrapping State Management

The testbench uses a static flag $hasBootstrappedTestbench at src/TestCase.php36 to ensure Bootstrapper::bootstrap() executes only once per test run, even when reloadApplication() is called:


Diagram: Bootstrap State Machine

This optimization prevents redundant file system operations and environment setup while still allowing application reloading within tests.

Sources: src/TestCase.php36-43


Dynamic Provider Management

Runtime Provider Manipulation

The ConfigProviderRegister class provides static methods for manipulating the provider registry at runtime. This allows tests to customize which framework components are loaded.


Diagram: Provider Registry Manipulation Methods

Example usage patterns:

OperationMethod CallUse Case
Add custom providerConfigProviderRegister::add(MyProvider::class)Register package-specific services
Remove unwanted providerConfigProviderRegister::except(\Hyperf\Devtool\ConfigProvider::class)Exclude unnecessary components
Conditional filteringConfigProviderRegister::filter(fn($p) => !str_contains($p, 'Redis'))Remove all Redis-related providers
Add multipleConfigProviderRegister::add([Provider1::class, Provider2::class])Bulk registration

Sources: src/ConfigProviderRegister.php59-87

Provider Manipulation in Tests

Provider manipulation typically occurs in defineEnvironment():


Note: Provider modifications must occur before the application boots. Modifying providers after setUp() completes has no effect for that test.

Sources: src/TestCase.php63-67 src/ConfigProviderRegister.php68-87


Coroutine Context Management

Coroutine Execution Wrappers

The testbench wraps key lifecycle methods in coroutine context using runInCoroutine() (inherited from Hypervel\Foundation\Testing\TestCase). This ensures Hyperf's async operations function correctly in tests.


Diagram: Coroutine Context Wrapping in Test Lifecycle

The coroutine wrappers at src/TestCase.php57 and src/TestCase.php83 ensure that:

  • Database operations execute in coroutine context
  • HTTP clients function correctly
  • Event listeners and queues operate properly
  • Swoole-specific features are available

Sources: src/TestCase.php38-88

Timer and Coordinator Management

Before each test, the testbench performs cleanup of Swoole timers and coordinator state:


Diagram: Timer and Coordinator Cleanup Sequence

This cleanup at src/TestCase.php46-47 prevents:

  • Timer leaks between tests
  • Coordinator deadlocks from previous test failures
  • Worker exit signals persisting across tests

The Constants::WORKER_EXIT constant from src/TestCase.php9 represents the coordinator used by Hyperf to manage graceful worker shutdown.

Sources: src/TestCase.php45-51 src/TestCase.php7-10


Resource Management and Cleanup

Test Isolation Strategies

The testbench employs multiple strategies to ensure test isolation:


Diagram: Test Isolation Mechanisms Across Lifecycle

Each mechanism addresses a specific resource category:

Resource TypeCleanup MethodLocationPurpose
Application containerNew instancesrc/TestCase.php69-78Prevent service state leakage
Swoole timersTimer::clearAll()src/TestCase.php46Remove pending callbacks
Coordinatorsresume() on WORKER_EXITsrc/TestCase.php47Reset async coordination state
Database schemadestroyDatabaseMigrations()Via HandlesDatabases traitClean up test tables
Queue payloadscreatePayloadUsing(null)src/TestCase.php87Clear custom serialization
ApplicationContextsetContainer()src/TestCase.php75Update global container reference

Sources: src/TestCase.php38-88

Queue Payload Cleanup

The queue payload callback reset at src/TestCase.php87 is particularly important for tests that customize job serialization:


Without this cleanup, custom payload callbacks from one test would affect subsequent tests, violating test isolation.

Sources: src/TestCase.php80-88


Class-Level Test Hooks

BeforeClass and AfterClass Integration

The testbench integrates with PHPUnit's class-level hooks through the HandlesAttributes and InteractsWithTestCase traits:


Diagram: Class-Level Hook Execution Order

The implementation at src/TestCase.php99-109 ensures proper ordering:

  1. Parent setUpBeforeClass() executes first (PHPUnit setup)
  2. Then setUpBeforeClassUsingTestCase() executes (Hypervel attributes)
  3. After all tests, tearDownAfterClassUsingTestCase() executes first (Hypervel cleanup)
  4. Finally, parent tearDownAfterClass() executes (PHPUnit cleanup)

This ordering allows Hypervel's attribute system (e.g., #[BeforeAll], #[AfterAll]) to function correctly within the PHPUnit test lifecycle.

Sources: src/TestCase.php99-109 src/TestCase.php15-17


Core Bindings and Contracts

Application Container Bindings

The createApplication() method establishes two critical contract bindings:


Diagram: Core Container Bindings in Application Creation

These bindings at src/TestCase.php72-73 provide:

ContractImplementationPurpose
KernelContractConsoleKernelConsole command execution interface
ExceptionHandlerContractWorkbench\App\Exceptions\ExceptionHandlerTest exception handling

The ApplicationContext::setContainer() call at src/TestCase.php75 updates Hyperf's global container reference, making the application instance accessible throughout the framework via ApplicationContext::getContainer().

Sources: src/TestCase.php69-78 src/TestCase.php7-8 src/TestCase.php11-14 src/TestCase.php20


Advanced Testing Patterns

Testing Provider Registration Order

Provider registration order can affect service resolution. To test order-dependent behavior:


This pattern completely controls provider registration order, useful for testing:

  • Service override behavior
  • Configuration merge order
  • Dependency resolution sequences

Sources: src/ConfigProviderRegister.php68-87

Testing with Modified Environment

Environment modifications should occur in defineEnvironment() before the application boots:


For runtime environment changes within a test, use reloadApplication() to reinitialize:


Sources: src/TestCase.php63-67 src/TestCase.php93-97


Summary

This page covered the advanced extension points and lifecycle management features of the Hypervel Testbench:

  • Extension Points: defineEnvironment(), defineRoutes(), defineWebRoutes(), afterApplicationCreated(), and reloadApplication()
  • Coroutine Management: Automatic wrapping via runInCoroutine(), timer cleanup, and coordinator reset
  • Resource Isolation: Per-test application instances, database cleanup, queue reset, and context management
  • Provider Management: Runtime manipulation via ConfigProviderRegister static methods
  • Class-Level Hooks: Integration with PHPUnit's setUpBeforeClass() and tearDownAfterClass()

For implementation details on specific topics:

Sources: src/TestCase.php1-110 src/ConfigProviderRegister.php1-88 src/Concerns/HandlesRoutes.php1-48