Skip to content

[ISSUE-48] Add Comprehensive Testing Utilities with MockServer and Request Recording#65

Merged
Thavarshan merged 9 commits into
mainfrom
48-enhanced-testing-utilities-mock-server
Nov 17, 2025
Merged

[ISSUE-48] Add Comprehensive Testing Utilities with MockServer and Request Recording#65
Thavarshan merged 9 commits into
mainfrom
48-enhanced-testing-utilities-mock-server

Conversation

@Thavarshan

Copy link
Copy Markdown
Owner

Description

This PR introduces a powerful testing framework for Fetch PHP, inspired by Laravel's HTTP client testing utilities. It provides developers with robust tools for testing HTTP-dependent code without making real network requests.

Key Features:

  • MockServer with URL pattern matching (wildcards, method-specific, callbacks)
  • MockResponse fluent builder with convenience methods for all HTTP status codes
  • MockResponseSequence for testing retry logic and flaky endpoints
  • Recorder for capturing and replaying request/response pairs
  • Comprehensive assertion helpers (assertSent, assertNotSent, assertSentCount)
  • Request recording with JSON export/import for test fixtures
  • Stray request prevention to ensure complete test coverage

Fixes #48

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Documentation update

Changes Made

Core Testing Utilities

1. MockResponse (src/Fetch/Testing/MockResponse.php)

  • Fluent builder for creating mock HTTP responses
  • Factory methods: create(), json(), sequence()
  • Convenience methods for all common HTTP status codes:
    • Success: ok(), created(), noContent()
    • Client errors: badRequest(), unauthorized(), forbidden(), notFound(), unprocessableEntity()
    • Server errors: serverError(), serviceUnavailable()
  • Support for response delays and exception throwing

2. MockResponseSequence (src/Fetch/Testing/MockResponseSequence.php)

  • Manages sequential responses for testing retry logic
  • Methods: push(), pushJson(), pushStatus(), pushResponse()
  • Support for default responses, looping, and resetting

3. MockServer (src/Fetch/Testing/MockServer.php)

  • Singleton mock server with pattern matching
  • URL patterns with wildcards (e.g., https://api.example.com/users/*)
  • Method-specific matching (e.g., POST https://api.example.com/users)
  • Callback-based dynamic responses
  • Stray request prevention with allowlist support
  • Assertion methods: assertSent(), assertNotSent(), assertSentCount(), assertNothingSent()
  • Request recording with filtering

4. Recorder (src/Fetch/Testing/Recorder.php)

  • Records and replays HTTP requests/responses
  • JSON export/import functionality for test fixtures
  • Methods: start(), stop(), replay(), exportToJson(), importFromJson()

5. HandlesMocking Trait (src/Fetch/Concerns/HandlesMocking.php)

  • Integrates mocking into ClientHandler
  • Non-invasive request interception
  • Compatible with existing request flow

Integration Changes

Modified Files:

  • src/Fetch/Http/ClientHandler.php - Added HandlesMocking trait
  • src/Fetch/Concerns/PerformsHttpRequests.php - Added mock request interception
  • src/Fetch/Http/Request.php - Added createFromBase() for PSR-7 conversion
  • src/Fetch/Concerns/ManagesPromises.php - Fixed async helper function imports
  • tests/Integration/AsyncRequestsTest.php - Fixed async helper function imports
  • tests/Unit/ManagesPromisesTest.php - Fixed async helper function imports

Documentation

New Documentation:

  • docs/guide/testing.md - Comprehensive testing guide with examples (617 lines)
  • docs/api/testing.md - Complete API reference (539 lines)
  • docs/.vitepress/config.mts - Added testing section to sidebar navigation

Documentation Highlights:

  • Quick start examples
  • URL pattern matching guide
  • Response sequences for retry testing
  • Request recording and playback
  • Assertion examples
  • Complete API reference with method signatures
  • Best practices for testing
  • Integration test examples

Tests

New Test Files:

  • tests/Unit/Testing/MockResponseTest.php - 40 tests, 82 assertions
  • tests/Unit/Testing/MockResponseSequenceTest.php - 28 tests, 72 assertions
  • tests/Unit/Testing/MockServerTest.php - 18 tests, 44 assertions
  • tests/Unit/Testing/RecorderTest.php - 15 tests, 31 assertions
  • tests/Integration/MockingIntegrationTest.php - 16 tests, 59 assertions

Total: 117 new tests with 288 assertions

Bug Fixes

Fixed pre-existing async helper function import issues by updating all imports to use the correct Matrix\Support\* namespace:

  • Functions fixed: async, await, all, any, race, reject, resolve, timeout

Testing

How has this been tested?

  • Unit tests added/updated - 117 new tests added
  • Integration tests added/updated - 16 integration tests
  • Manual testing performed - Tested with various HTTP scenarios
  • All existing tests pass - All 282 tests passing with 841 assertions

Test Coverage:

  • MockResponse: 40 tests covering all factory methods, convenience methods, delays, and exceptions
  • MockResponseSequence: 28 tests covering push operations, looping, defaults, and reset
  • MockServer: 18 tests covering pattern matching, callbacks, assertions, and stray requests
  • Recorder: 15 tests covering recording, playback, JSON export/import, and state management
  • Integration: 16 tests covering real-world usage patterns

Test Environment:

  • PHP Version: 8.3, 8.4
  • Operating System: Ubuntu, macOS, Windows (CI)
  • All tests pass on all supported PHP versions and platforms

Code Quality:

  • PHPUnit: 282/282 tests passing, 841 assertions
  • Duster (code style): All checks passing
  • PHPStan (static analysis): Level max, no errors
  • PSR-12 compliance: All files compliant

Documentation

  • Code is self-documenting with clear variable names and logic
  • PHPDoc comments added for all public methods
  • README.md updated (not applicable - covered in docs/)
  • CHANGELOG.md updated (to be done in separate commit)
  • Comprehensive testing guide added (docs/guide/testing.md)
  • Complete API reference added (docs/api/testing.md)
  • VitePress sidebar navigation updated

Checklist

  • My code follows the project's coding standards
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings or errors
  • I have added tests that prove my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Usage Examples

Basic Mocking

use Fetch\Testing\MockServer;
use Fetch\Testing\MockResponse;

// Set up fake responses
MockServer::fake([
    'https://api.example.com/users' => MockResponse::json(['users' => []]),
]);

// Make requests (they will be mocked)
$response = get('https://api.example.com/users');

// Assert requests were sent
MockServer::assertSent('https://api.example.com/users');

Testing Retry Logic

MockServer::fake([
    'https://api.example.com/flaky' => MockResponse::sequence()
        ->pushStatus(503)  // First request fails
        ->pushStatus(503)  // Second request fails
        ->pushStatus(200), // Third request succeeds
]);

$response = retry(fn() => get('https://api.example.com/flaky'), 3);
MockServer::assertSent('https://api.example.com/flaky', 3);

Recording and Replaying Requests

use Fetch\Testing\Recorder;

// Record real requests
Recorder::start();
$response = get('https://api.example.com/users');
$json = Recorder::exportToJson();

// Later, replay the recordings
Recorder::importFromJson($json);
$response = get('https://api.example.com/users'); // Returns recorded response

Additional Notes

Architecture Decisions:

  1. Singleton Pattern: Both MockServer and Recorder use singleton pattern for global test state management, similar to Laravel's approach.

  2. Trait-based Integration: HandlesMocking trait provides clean separation and easy integration into the existing ClientHandler architecture.

  3. PSR-7 Compatibility: Full compatibility with PSR-7 HTTP messages maintained throughout.

  4. Non-invasive Interception: Mock interception happens at the request execution level, preserving all existing functionality.

  5. Pattern Matching: Flexible pattern matching with wildcards and method prefixes provides powerful test configuration options.

Performance Considerations:

  • Mocking adds negligible overhead when not active
  • All mock lookups use efficient array access
  • Response sequences use simple array iteration

Future Enhancements (out of scope for this PR):

  • Advanced pattern matching with regex support
  • Request history inspection utilities
  • Mock response templates
  • Automatic fixture generation

Breaking Changes: None - this is a purely additive feature that doesn't affect existing functionality.

Thavarshan and others added 2 commits November 17, 2025 08:53
…, and request recording

Implements a powerful testing framework inspired by Laravel's HTTP client testing,
adapted for Fetch PHP's architecture. This provides developers with robust tools
for testing HTTP-dependent code without making real network requests.

Features:
- MockServer with URL pattern matching (wildcards, method-specific, callbacks)
- MockResponse fluent builder with convenience methods for all HTTP status codes
- MockResponseSequence for testing retry logic and flaky endpoints
- Recorder for capturing and replaying request/response pairs
- Comprehensive assertion helpers (assertSent, assertNotSent, assertSentCount)
- Request recording with JSON export/import for test fixtures
- Stray request prevention to ensure complete test coverage
- Response delays and exception throwing for edge case testing

Implementation Details:
- Added MockServer singleton for centralized mock management
- Created MockResponse with 10+ convenience factory methods
- Implemented HandlesMocking trait integrated into ClientHandler
- Added Request::createFromBase() for PSR-7 request wrapping
- Modified PerformsHttpRequests to intercept and mock requests

Testing:
- 84 tests with 182 assertions (all passing)
- Unit tests for MockServer, MockResponse, Sequence, and Recorder
- Integration tests demonstrating real-world usage patterns
- Full PHPStan level max compliance
- PSR-12 code style compliance

Documentation:
- Updated /guide/testing with comprehensive MockServer examples
- Added /api/testing with complete API reference
- Integrated testing docs into VitePress sidebar navigation
- Removed outdated Guzzle MockHandler examples

Closes #48

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Updated all async helper function imports to use the correct namespaced paths
from the Matrix library (Matrix\Support\*). The Matrix library has namespaced
these helper functions, so imports need to use the full namespace.

Fixed in:
- src/Fetch/Concerns/ManagesPromises.php (all, any, async, await, race, reject, resolve, timeout)
- src/Fetch/Concerns/PerformsHttpRequests.php (async)
- tests/Unit/ManagesPromisesTest.php (async, await, reject, resolve)
- tests/Integration/AsyncRequestsTest.php (all, async, await)

All 282 tests now passing with 841 assertions.

Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@Thavarshan Thavarshan self-assigned this Nov 17, 2025
@Thavarshan Thavarshan added documentation Improvements or additions to documentation enhancement New feature or request labels Nov 17, 2025
@Thavarshan Thavarshan linked an issue Nov 17, 2025 that may be closed by this pull request
@netlify

netlify Bot commented Nov 17, 2025

Copy link
Copy Markdown

Deploy Preview for fetch-php canceled.

Name Link
🔨 Latest commit 6ba32f6
🔍 Latest deploy log https://app.netlify.com/projects/fetch-php/deploys/691a9df289d682000827446c

Thavarshan and others added 4 commits November 17, 2025 09:07
Removed Dependabot integration to simplify dependency management:
- Deleted .github/dependabot.yml (Composer, NPM, and GitHub Actions updates)
- Deleted .github/workflows/dependabot-auto-merge.yml (auto-merge workflow)

Note: The dependency-review.yml workflow remains active for security reviews on PRs.

Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Added comprehensive changelog entry for v3.3.0 including:
- New testing utilities (MockServer, MockResponse, MockResponseSequence, Recorder)
- 117 new tests with 288 assertions
- Comprehensive testing documentation
- Fixed async helper function imports
- Removed Dependabot configuration

Also cleaned up duplicate entries at the end of the changelog.

Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Changed `allow-dependencies-licenses` to `allow-licenses` parameter.
The incorrect parameter name was causing package-url parsing errors.

Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 17, 2025

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
composer/jerome/matrix >= 3.4, < 4.0 UnknownUnknown

Scanned Files

  • .github/workflows/dependabot-auto-merge.yml
  • composer.json

Thavarshan and others added 3 commits November 17, 2025 09:14
The pcntl extension is Unix-only and not available on Windows.
Added --ignore-platform-req=ext-pcntl flag for Windows builds
to allow composer install to succeed.

Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The --prefer-lowest flag only works with 'composer update', not 'composer install'.
Split the install step into two conditional steps:
- Regular install for stable builds
- Update with --prefer-lowest for lowest dependency builds

Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@Thavarshan Thavarshan merged commit 0a50f4b into main Nov 17, 2025
21 checks passed
@Thavarshan Thavarshan deleted the 48-enhanced-testing-utilities-mock-server branch June 6, 2026 06:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change documentation Improvements or additions to documentation enhancement New feature or request performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhanced Testing Utilities & Mock Server

1 participant