mrgoodbytes8667/test-twitch-faker
A testing helper for Laravel apps that fakes Twitch API responses, letting you swap real HTTP calls for predictable fixtures so your tests run fast and offline. Mock streams, users, and webhook payloads without ever hitting the live Twitch API.
mrgoodbytes8667/test-twitch-faker is a dev-only companion to the Twitch client package: it supplies fake implementations of the client/response contracts so your feature tests never touch the real Twitch API.
Install (dev only):
composer require --dev mrgoodbytes8667/test-twitch-faker
Where to look first, in this order:
composer.json of the faker — note the mrgoodbytes8667/twitch constraint it was built against. At 0.0.x these two packages are version-locked in practice.src/ — the fake classes and which interfaces they implement. That interface list is the API surface you can rely on.tests/ directory — at 0.0.x there is no meaningful docs site, so the package's test suite is the de facto documentation for constructor arguments and response-shaping helpers.First use case — stop a controller from hitting Twitch:
protected function setUp(): void
{
parent::setUp();
// Bind before the app resolves the client (in setUp, not in the test body)
$this->app->instance(TwitchClient::class, new FakeTwitchClient());
}
Then write a normal feature test against your own route. If the test passes with networking disabled, the swap worked.
Per-test binding, not a singleton. Instantiate the fake fresh in setUp() (or a dedicated trait) rather than registering it in a service provider. Fakes accumulate state — recorded calls, queued responses, cursors — and a shared instance will leak that state across tests in the same process, producing order-dependent failures that are miserable to debug.
A FakesTwitch trait is the right abstraction once more than two test classes need this:
trait FakesTwitch
{
protected FakeTwitchClient $twitch;
protected function fakeTwitch(): FakeTwitchClient
{
return $this->twitch = $this->app->make(FakeTwitchClient::class);
}
}
Queue responses per call, assert on your app's output. The healthy pattern is: seed the fake with the payloads you want, call your endpoint, then assert on your JSON/resources/DB rows — not on the fake's internal call log. Asserting on the fake couples your test suite to the faker's internals, which at 0.0.x will churn.
Keep raw Twitch payloads as fixtures. Store real captured responses under tests/Fixtures/twitch/*.json and feed them to the fake. This gives you two things: realistic shape coverage (Twitch nests heavily under data), and a one-line diff when the upstream schema shifts.
Works cleanly in queued jobs and console commands because the container swap is global for the test — no special handling needed. Just make sure the job is dispatched after setUp() runs.
Layer with Http::fake() only if needed. If the faker sits at the client-contract level, you generally don't need HTTP faking at all — but be aware of which layer you've faked. Mixing both without understanding the boundary is how you get tests that pass while production 401s.
Integration tip: if you cache Twitch tokens or store channel data, combine with RefreshDatabase and clear the relevant cache keys in setUp() — a cached real-client result will happily survive your fake binding.
0.0.x versioning is the headline risk. Composer's caret behaves differently below 1.0: ^0.0.6 resolves to >=0.0.6 <0.0.7, i.e. it pins the patch. That's accidentally a good thing — but it also means composer update will not pick up 0.0.7 unless you bump the constraint manually. Bump deliberately and run the full suite, don't blind-update.
v0.0.7 shipped no release notes. The changelog entry is only a compare link (v0.0.6...v0.0.7). Before adopting it, run:
git diff v0.0.6..v0.0.7 -- src/
Check specifically whether any fake class changed its constructor signature or which interface methods it implements. A fake gaining required constructor arguments is a silent breaking change for every new FakeTwitchClient() in your suite — the failure surfaces as an ArgumentCountError at test time, which is at least loud, but a fake losing a method surfaces as a fatal only on the tests that reach that code path.
Fakes lag behind the real client. When you upgrade mrgoodbytes8667/twitch, the faker may not yet implement newly added interface methods, and PHP will fail the class at autoload. Symptom: a fatal Class ... contains 1 abstract method rather than a test failure. Fix by pinning the pair together, or by extending the fake locally.
Never let the faker reach a non-test environment. It's require-dev, so it should be absent in production — but if you reference fake class names in application code (e.g. a conditional binding in a service provider keyed on app()->environment()), you'll get a class-not-found in prod. Keep every reference inside tests/.
Extension points: subclass the provided fake to add domain-specific canned responses, and prefer that over editing vendor files. If the fake exposes a way to register responses by endpoint/verb, wrap it in your own small helper so a future upstream signature change touches one file.
Debugging: when a test still appears to hit the network, dump(app(TwitchClient::class)::class) at the top of the test. Nine times out of ten the binding ran after something already resolved and memoized the real client — move it earlier, or bind via the container before the first $this->get().
How can I help you explore Laravel packages today?