php-http/client-integration-tests
Integration test suite for PHP HTTP clients and adapters. Provides a shared test server and PHPUnit testsuite so you can verify that your client correctly implements the PSR-18 and HTTPlug contracts against real HTTP requests.
What the package actually is. php-http/client-integration-tests is not an application testing library. It is a black-box conformance suite for teams that implement or maintain a PSR-18 HTTP client (or a wrapper around one). It ships an IntegrationTestCase you subclass, a local test HTTP server (vendor/bin/http_test_server), per-adapter PHPUnit testsuites, and a custom result printer, then runs a broad battery of assertions covering redirects, auth, timeouts, streaming, header semantics, and optionally async transports. The README states the constraint plainly: "This package should not be used on its own."
That framing drives everything below. For a typical Laravel product team using Illuminate\Support\Facades\Http (Guzzle under the hood, already validated upstream), leverage is close to zero — there is no seam to plug into. The addressable audience is narrow: a platform team that authors an internal HTTP client abstraction, forks or pins an adapter, or is running a formal bake-off between client libraries.
Architecture fit — weak-to-moderate, conditional. Laravel's Http::fake() and Http::preventStrayRequests() cover application-level HTTP testing; php-http/mock-client covers unit-level mocking. This package occupies a different, much thinner layer: proving a client implementation speaks PSR-18 and PSR-7 correctly. The dependency is require-dev only — zero runtime footprint — which caps both the upside and the blast radius. The correct TPM posture is a conditional yes: approve only if we can name the client implementation we own. If we cannot, this is a no-op and the evaluation ends.
Integration feasibility — mechanically easy, operationally non-trivial. Composer install, one subclass, one testsuite entry, one CI job. But this is a network-and-process test suite, not a unit suite, and each of those properties is a workstream:
httpbin.org. Anything hitting a public endpoint introduces egress, rate-limit, and availability failure modes outside our control.ext-uv/ReactPHP and an optional HTTPlug 2.0 install; the practical answer is --exclude-group async, which reduces effective coverage below the headline.Technical risk — low-to-moderate, and mostly supply-chain verification rather than runtime risk. Mitigants: MIT license, php-http is the legitimate HTTPlug organization, a changelog going back to 0.1.0, and a dev-only dependency that cannot reach production. Concerns:
Key questions.
httpbin.org versus the bundled local server, and can we run 100% offline on the pinned version?Stack fit — treat this as a platform-engineering tool, not an app-team dependency. Three legitimate uses:
curl-client — objective, standards-anchored, comparable across candidates in a way opinion is not.It does not replace Http::fake(), Http::preventStrayRequests(), or contract tests against our own API consumers. State that boundary explicitly in the adoption RFC; otherwise expect scope creep into application test suites, where the package adds cost and no value.
Migration path — greenfield, additive, reversible.
composer require --dev php-http/client-integration-tests pinned to an exact minor, in the adapter package rather than the main application.tests/Integration/<OurClient>IntegrationTest.php extending the provided base test case; implement createClient() and getOptions() so we exercise our configured stack (retries, logging, auth middleware), not a bare client.phpunit.xml mirroring the README's --testsuite curl pattern, and keep it out of the default run.--exclude-group async; enable async only if we genuinely ship an async transport.Compatibility — pin package and PHPUnit together. These test classes break on PHPUnit majors in ways discovered only at runtime. Budget an upgrade task whenever Laravel's PHPUnit major moves. Also verify PSR-17 factory availability (laminas/laminas-diactoros or nyholm/psr7): 4.0.0 replaced $messageFactory with $requestFactory/$streamFactory, which is a hard break for any subclass written against 3.x. Note also that 4.1.x allows guzzlehttp/psr7 v3 and relaxes the HEAD Content-Length expectation — pinning to the version whose semantics we accept matters more than pinning to "latest."
Sequencing.
Maintenance. The dependency itself is static; the CI job is what rots. Upstream is single-org and volunteer-run, so expect long gaps between releases and little appetite for bespoke bug reports. Our steady-state cost is roughly 2–4 engineer-days per year, spiking to about a week in a PHPUnit-migration year. One real lever: the project has a contributing guide and accepts PRs, so we can fix our own breakages and upstream them rather than waiting.
Support. No vendor, no SLA. Channels are GitHub issues and the php-http docs site. The escalation path is to vendor the specific test classes we use — the codebase is small and MIT-licensed, so forking is a credible last resort rather than a rewrite. That is the single most important fact for a TPM sign-off: the exit cost is low.
Scaling. Fine as a narrow gate, poor as a general practice. Each client under test means one subclass, one testsuite, and one CI job with its own server process and port. Running this across many adapters multiplies CI minutes and server-management overhead for diminishing returns. Constrain it to clients we own — realistically zero or one. Its value is concentrated, not distributed.
Failure modes, ranked by likelihood.
httpbin.org — rate limits and outages. Mitigate by pinning a version that uses the bundled server, or by running our own httpbin container.Ramp-up. Low for an individual PHP developer: Composer plus a subclass plus a phpunit.xml entry is about half a day if the spike passes. The organizational prerequisite is conceptual, not mechanical — PSR-18/PSR-7/PSR-17 literacy, understanding which factory does what, why HEAD responses omit Content-Length, and why TRACE bodies are invalid per RFC 7231. Designate one engineer as HTTP-client owner; do not fan this out. Onboarding doc should be one page: how to run the server locally, the testsuite name, the pin policy, and the explicit statement of what this suite does not cover.
How can I help you explore Laravel packages today?