mediumFull Stack EngineerProduct
How do you mock dependencies in tests, and what are the different mocking strategies?
Posted 18/04/2026
by Mehedy Hasan Ador
Question Details
At a product company:
> "Our unit tests for the payment service call the real Stripe API. Sometimes tests fail because Stripe is down, not because our code is broken. How should we mock external dependencies?"
> "Our unit tests for the payment service call the real Stripe API. Sometimes tests fail because Stripe is down, not because our code is broken. How should we mock external dependencies?"
Suggested Solution
Mocking Strategies
1. Function Mocking (Jest/Vitest)
import { vi } from "vitest";
// Mock a module
vi.mock("@/lib/stripe", () => ({
chargeCard: vi.fn().mockResolvedValue({ id: "ch123", status: "succeeded" }),
}));
// Use in test
import { chargeCard } from "@/lib/stripe";
test("processPayment succeeds", async () => {
const result = await processPayment({ amount: 1000, card: "tokvisa" });
expect(result.success).toBe(true);
expect(chargeCard).toHaveBeenCalledWith({ amount: 1000, card: "tokvisa" });
});
2. Spy (wrap real function, track calls)
import { vi } from "vitest";
test("logs on error", async () => {
const logSpy = vi.spyOn(logger, "error");
await expect(failingFunction()).rejects.toThrow();
expect(logSpy).toHaveBeenCalledWith("Function failed", expect.any(Error));
});
3. Dependency Injection
// Production code accepts dependencies
class PaymentService {
constructor(private stripe: StripeClient) {}
async process(amount: number) {
return this.stripe.charge({ amount });
}
}
// Test with mock injected
const mockStripe = { charge: vi.fn().mockResolvedValue({ id: "ch123" }) };
const service = new PaymentService(mockStripe as any);
4. MSW (Mock Service Worker) — API mocking
import { setupServer } from "msw/node";
import { http, HttpResponse } from "msw";
const server = setupServer(
http.post("/api/payments", () => {
return HttpResponse.json({ id: "ch_123", status: "succeeded" });
})
);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
// Now fetch("/api/payments") returns mocked response
// Works in both unit and integration tests
When to Use What
vi.mock()vi.spyOn()