Skip to content

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

Merged
Thavarshan merged 9 commits intomainfrom
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 intomainfrom
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
Copy link
Copy Markdown

netlify Bot commented Nov 17, 2025

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
Copy link
Copy Markdown
Contributor

github-actions Bot commented Nov 17, 2025

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
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