This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a Codeception module for integrating with WireMock, a tool for mocking HTTP services in tests. The module extends Codeception's base Module class to provide WireMock functionality to Codeception test suites.
Key Details:
- PHP 8.2+ required
- Codeception 5.3+ required
- PSR-18 (HTTP Client) and PSR-17 (HTTP Factories) required
- Guzzle HTTP client optional (auto-discovered if available)
- MIT licensed
- PSR-4 autoloading structure
Architecture:
- Depends on PSR-18/PSR-17 interfaces (true dependency inversion)
- No hard dependency on Guzzle - any PSR-compliant HTTP client works
- Optional auto-discovery creates Guzzle instances if available
- Users can inject their own PSR-18/PSR-17 implementations
src/JasonBenett/CodeceptionModuleWiremock/
├── Module/
│ └── Wiremock.php # Main module class with all public methods
├── Exception/
│ ├── WiremockException.php # Base exception
│ └── RequestVerificationException.php # Verification failure exception
└── Http/
└── HttpClientException.php # PSR-18 ClientExceptionInterface implementation
tests/
├── unit/
│ └── Codeception/Module/
│ └── WiremockTest.php # Unit tests with mocked HTTP client
├── functional/
│ └── WiremockIntegrationCest.php # Integration tests against real WireMock
└── _support/
└── FunctionalTester.php # Functional tester actor
composer install # Install dependencies
composer update # Update dependencies
composer dump-autoload # Regenerate autoload filescomposer test # Run unit tests
composer test:functional # Run functional tests (requires WireMock running)
composer phpstan # Run static analysis
composer cs-check # Check code style
composer cs-fix # Fix code style issuesdocker run -d -p 8080:8080 wiremock/wiremock:latest # Start WireMock server on port 8080
docker ps | grep wiremock # Check if WireMock is running
docker logs <container-id> # View WireMock logs
docker stop <container-id> # Stop WireMock serverIMPORTANT: This project uses Conventional Commits specification for all commit messages.
Format:
<type>(<optional scope>): <description>
[optional body]
[optional footer(s)]
Types:
feat:- New feature for usersfix:- Bug fix for usersdocs:- Documentation changesstyle:- Code style changes (formatting, missing semi colons, etc)refactor:- Code refactoring (neither fixes a bug nor adds a feature)perf:- Performance improvementstest:- Adding or updating testschore:- Changes to build process, CI, dependencies, etc
Examples:
# Feature addition
git commit -m "feat: add support for delayed stub responses"
# Bug fix
git commit -m "fix: handle empty response body in makeAdminRequest"
# Refactoring
git commit -m "refactor: extract HTTP client abstraction to use PSR-18"
# Documentation
git commit -m "docs: update README with PSR configuration examples"
# Breaking change
git commit -m "feat!: replace Guzzle with PSR-18 interfaces
BREAKING CHANGE: httpClient, requestFactory, and streamFactory are now required configuration options"All commits MUST:
- Follow the conventional commits format
- Include the footer:
🤖 Generated with [Claude Code](https://claude.com/claude-code) - Include:
Co-Authored-By: Claude <noreply@anthropic.com>
IMPORTANT: The CHANGELOG.md file MUST be updated for every user-facing change.
Format: We follow Keep a Changelog format.
Workflow:
-
During Development: Add changes to the
[Unreleased]section under appropriate category:### Added- New features### Changed- Changes in existing functionality### Deprecated- Soon-to-be removed features### Removed- Removed features### Fixed- Bug fixes### Security- Security fixes
-
Before Release: Move
[Unreleased]changes to a new version section:## [1.1.0] - 2025-02-15 ### Added - New feature description
-
Update Guidelines:
- Write for users, not developers (focus on behavior, not implementation)
- Be specific about what changed and why users care
- Link to issues/PRs when relevant:
(#123) - For breaking changes, explain migration path
Example Entry:
## [Unreleased]
### Added
- Support for custom HTTP headers in all stub methods
### Changed
- `haveHttpStubFor()` now validates request matchers before sending to WireMock
### Fixed
- Near-miss analysis now handles special characters in URLs correctly-
Before Committing:
- Run all quality checks:
composer test && composer phpstan && composer cs-check - Update CHANGELOG.md if user-facing changes
- Verify all tests pass
- Run all quality checks:
-
Committing:
- Use semantic commit message format
- Include Claude Code footer
-
Pull Requests:
- Ensure CI passes (all PHP versions, all checks)
- Update README.md if API changes
- Update CHANGELOG.md in Unreleased section
The module accepts the following configuration in codeception.yml:
modules:
enabled:
- \JasonBenett\CodeceptionModuleWiremock\Module\Wiremock:
host: localhost # Required: WireMock host (default: 127.0.0.1)
port: 8080 # Required: WireMock port (default: 8080)
protocol: http # Optional: Protocol (default: http)
cleanupBefore: test # Optional: When to cleanup: 'never', 'test', or 'suite' (default: test)
preserveFileMappings: true # Optional: Keep file-based stubs on reset (default: true)
adminPath: /__admin # Optional: Admin API path (default: /__admin)
httpClient: null # Optional: PSR-18 ClientInterface instance (auto-creates Guzzle if null)
requestFactory: null # Optional: PSR-17 RequestFactoryInterface instance (auto-creates if null)
streamFactory: null # Optional: PSR-17 StreamFactoryInterface instance (auto-creates if null)Note: If PSR client instances are not provided, the module will automatically create Guzzle instances if guzzlehttp/guzzle is installed. For custom HTTP clients, provide PSR-18/PSR-17 implementations.
haveHttpStubFor(string $method, string $url, int $status = 200, $body = '', array $headers = [], array $requestMatchers = []): string- Create stub for any HTTP method
seeHttpRequest(string $method, string $url, array $additionalMatchers = []): void- Verify request was madedontSeeHttpRequest(string $method, string $url, array $additionalMatchers = []): void- Verify request was NOT madeseeRequestCount(int $count, array $requestPattern): void- Assert exact request count
grabRequestCount(array $requestPattern): int- Get request countgrabAllRequests(): array- Get all recorded requestsgrabUnmatchedRequests(): array- Get requests that didn't match any stub
sendReset(): void- Reset stubs to default (preserves file-based mappings)sendClearRequests(): void- Clear request journal without affecting stubs
_initialize()- Validates/creates PSR-18/PSR-17 clients and verifies WireMock connectivity_beforeSuite()- Cleanup ifcleanupBefore: suite_before()- Cleanup ifcleanupBefore: test(default behavior)
initHttpClient(): void- Get PSR-18 client from config or auto-create Guzzle instanceinitRequestFactory(): void- Get PSR-17 request factory from config or auto-createinitStreamFactory(RequestFactoryInterface): void- Get PSR-17 stream factory from config or auto-createmakeAdminRequest(string, string, array): array- Make HTTP request to WireMock Admin API using PSR-18/PSR-17
POST /__admin/mappings- Create stub mappingPOST /__admin/mappings/reset- Reset to defaultsPOST /__admin/reset- Full reset (mappings + requests)DELETE /__admin/requests- Clear request journalPOST /__admin/requests/count- Count matching requestsGET /__admin/requests- Get all requestsGET /__admin/requests/unmatched- Get unmatched requestsPOST /__admin/near-misses/request- Get near-miss analysisGET /__admin/health- Health check
-
Start WireMock server:
docker run -d -p 8080:8080 wiremock/wiremock:latest
-
Wait for WireMock to be ready:
curl http://localhost:8080/__admin/health # Should return: {"status":"OK"} -
Run unit tests (don't require WireMock):
composer test -
Build Codeception support classes:
vendor/bin/codecept build
-
Run functional tests (require WireMock):
composer test:functional
- Use
grabAllRequests()to see all requests made - Use
grabUnmatchedRequests()to see requests that didn't match any stub - Check WireMock logs:
docker logs <container-id> - Near-miss analysis is automatically included in verification error messages
$I->haveHttpStubFor('GET', '/api/test', 200, 'Hello World');
$I->seeHttpRequest('GET', '/api/test');$I->haveHttpStubFor('GET', '/api/users/1', 200, [
'id' => 1,
'name' => 'John Doe'
]);$I->haveHttpStubFor('POST', '/api/users', 201, ['success' => true], [], [
'bodyPatterns' => [
['equalToJson' => ['name' => 'Jane Doe']]
]
]);$I->seeRequestCount(3, ['method' => 'GET', 'url' => '/api/data']);$unmatched = $I->grabUnmatchedRequests();
codecept_debug($unmatched);haveDelayedStub()- Simulate slow responseshaveMultipleStubs()- Bulk import stubsseeNoUnmatchedRequests()- Assert all requests matchedgrabNearMisses()- Explicit near-miss analysisgrabStubMapping()- Retrieve specific stubsendFullReset()- Public method for complete reset- Scenario/state management support
- Request templating support
- File-based stub import helper