One idea
Use a test double only when the real dependency makes the test slow, flaky, costly, or hard to control.
Do not fake the code you are trying to prove. Fake the outside thing your code talks to.
What doubles replace
A test double is a stand-in used during a test. It can replace an email sender, payment gateway, database, clock, file system, map service, or AI API call.
In hackathon projects, this often means you do not call Razorpay, Firebase, Google Maps, SendGrid, or an LLM API in a unit test. You replace that call with a small fake result.
Common mistake
Beginners mock every function. Then the test only proves that mocks return what the test wrote inside them.
If your test mocks your own business logic, it is weak. For example, do not mock calculateTotal() when the purpose is to test checkout pricing.
Use safely
Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.
0 of 5 done
Small Node example
Here the code sends an OTP only after saving it. The test fakes the SMS service because sending a real SMS costs money and can fail for reasons outside your code.
The fake records what would have been sent. The test still checks real app behaviour.
// otp.js
async function sendLoginOtp(phone, store, smsClient) {
const otp = "123456";
await store.saveOtp(phone, otp);
await smsClient.send(phone, `Your OTP is ${otp}`);
return { ok: true };
}
module.exports = { sendLoginOtp };
// otp.test.js
const { sendLoginOtp } = require("./otp");
test("saves OTP and asks SMS client to send it", async () => {
const saved = [];
const sent = [];
const fakeStore = {
saveOtp: async (phone, otp) => saved.push({ phone, otp })
};
const fakeSmsClient = {
send: async (phone, message) => sent.push({ phone, message })
};
const result = await sendLoginOtp("9876543210", fakeStore, fakeSmsClient);
expect(result).toEqual({ ok: true });
expect(saved).toEqual([{ phone: "9876543210", otp: "123456" }]);
expect(sent[0].phone).toBe("9876543210");
expect(sent[0].message).toContain("123456");
});AI check
If you ask ChatGPT, Gemini, or Claude to write tests with mocks, also ask: “What real behaviour does this test prove, and what could still break in production?”
Check that the answer names the external dependency being faked. If it cannot, the mock is probably hiding too much.
Do not fake contracts
If your fake returns a shape the real service never returns, your test gives false confidence. Keep fake responses copied from real docs, real logs, or a saved response from your app.
For example, if your payment API returns amount in paise, do not let your fake return rupees. That bug can reach production.
Do this now
Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.
0 of 5 done