Mocking
Introduction
When a feature dispatches jobs, sends mail, or writes files, tests usually should not hit the real driver. Bunyad packages expose .fake() helpers that record activity in memory so you can assert after the code under test runs.
There is no Mockery-style $this->mock(Service::class) on TestCase. Bind a hand-rolled stub with app.instance(...) when you need to replace a container service.
Events
import { Event } from "@bunyad/events";
import UserRegistered from "@/Events/UserRegistered.ts";
const fake = Event.fake();
await this.postJson("/register", { /* … */ });
Event.assertDispatched(UserRegistered);
Event.assertDispatched(UserRegistered, (e) => e.user.email === "ada@example.com");
Event.assertDispatchedTimes(UserRegistered, 1);
Event.assertNothingDispatched(); // or assertNotDispatched(Type)
fake.restore();Pass an allow-list to fake only some events; others still run listeners: Event.fake([UserRegistered]).
Details: Events.
import { Mail } from "@bunyad/mail";
Mail.fake();
await this.postJson("/register", { /* … */ });
Mail.assertSent(WelcomeMail);
Mail.assertSent((m) => String(m.to).includes("ada@example.com"));
Mail.assertSentCount(1);
Mail.assertNothingSent();
Mail.restore();Details: Mail.
Notifications
import { Notification } from "@bunyad/notifications";
Notification.fake();
Notification.assertSentTo(user, WelcomeNotification);
Notification.assertSentTimes(WelcomeNotification, 1);
Notification.assertSentOnDemand(OnDemandNote);
Notification.assertNothingSent();Details: Notifications.
Queues
import { Queue } from "@bunyad/queue";
Queue.fake();
await dispatch(new ProcessPodcast(podcast));
Queue.assertPushed(ProcessPodcast);
Queue.assertPushed(ProcessPodcast, (job) => job.queue === "podcasts");
Queue.assertPushedTimes(ProcessPodcast, 1);
Queue.assertNothingPushed();Details: Queues.
Cache
import { Cache } from "@bunyad/cache";
Cache.fake();
await Cache.put("user:1", { name: "Ada" });
await Cache.assertHas("user:1");
await Cache.assertHasValue("user:1", { name: "Ada" });
await Cache.assertMissing("gone");
Cache.restore();Details: Cache.
Storage
import { Storage } from "@bunyad/filesystem";
const fake = Storage.fake(); // or Storage.fake("s3")
await Storage.put("avatars/ada.png", bytes);
fake.assertExists("avatars/ada.png");
fake.assertMissing("avatars/missing.png");
fake.assertDirectoryEmpty("tmp");Details: File Storage.
Container stubs
Replace a bound service for one test:
this.app.instance(PaymentGateway, {
charge: async () => ({ id: "ch_test" }),
});Prefer fakes for facades. Use instance when the code under test resolves a concrete class from the container.
Uploaded files
Build a fake upload without touching disk:
import { UploadedFile } from "@bunyad/http";
const file = UploadedFile.fake().create("avatar.png", "…", "image/png");