š Mocking Data and Events in Jest ā Expense Tracker Edition
and spy on its own functions like a detective.
š Mocking Data and Events in JestāāāExpense TrackerĀ Edition

Our Expense Tracker has come a long way
it can mock APIs,
tame dependencies,
bend time,
and spy on its own functions like a detective.
But there is one type of chaos still left in the world:
random data and unpredictable events.
The stuff that happens whenever it wants.
Data from users,
Notifications,
Button clicks,
Sensors,
You have 1 new expense! pop-ups,
All the unpredictable messiness of real apps.
Today, we are going to tame that.
Weāll teach Jest how to handle fake data, fake events, and fake scenariosāāāall without touching the real world.
š” Why Data & Events Are Hard toĀ Test

Real data is messy.
Sometimes it comes too early,
Sometimes too late,
Sometimes not at all.
Sometimes users send you things like "Hello" where you expectedĀ { amount: 500 }.
And events?
They fire whenever they feel like it.
Tap events, input changes, notifications, callbacks firing three times because someone double-clicked too fast.
We cannot trust these things in tests.
We need control.
And control comes from mocking data and events.
š§© Step 1āāāMocking FakeĀ Data
Letās start simple.
Imagine your Expense Tracker loads a list of expenses from an API and normalizes them:
š expenseNormalizer.js
exports.normalizeExpenses = (list) => {
return list.map(item => ({
id: item.id,
amount: Number(item.amount),
category: item.category || 'Unknown',
}));
};Now, instead of relying on real API data, we can mock our own list:
š expenseNormalizer.test.js
const { normalizeExpenses } = require('./expenseNormalizer');
test('should normalize expenses correctly', () => {
const fakeData = [
{ id: 1, amount: "200", category: "Food" },
{ id: 2, amount: 300 }, // no category
];
const result = normalizeExpenses(fakeData);
expect(result[0].amount).toBe(200);
expect(result[1].category).toBe('Unknown');
});No API call.
No waiting.
Just pure, clean, fake data that behaves exactly how we need it to.
If you ever hear a dev saying, āIāll mock it later,ā
they actually mean:
āIāll lie to my code until the truth arrives.ā
And honestlyā¦
it works.
āļø Step 2āāāMocking Events (The FunĀ Part)
Letās add a tiny event-based feature:
Whenever a user adds a new expense, we fire a listener:
š expenseEvents.js
exports.onNewExpense = (listener) => {
// listener gets called whenever an expense is added
return listener;
};And our event trigger:
exports.addExpense = (data, listener) => {
listener(data);
return true;
};Now in our test:
š expenseEvents.test.js
const { addExpense } = require('./expenseEvents');
test('should call listener when new expense is added', () => {
const fakeListener = jest.fn();
addExpense({ amount: 500 }, fakeListener);
expect(fakeListener).toHaveBeenCalled();
expect(fakeListener).toHaveBeenCalledWith({ amount: 500 });
});Boom š„āāāevent tested, no UI needed.
This is how real apps test interactions behind the scenes.
š§ Step 3āāāMocking Randomness
Sometimes functions depend on randomness:
discounts, unique IDs, random numbers, date stampsā¦
Example:
š expenseId.js
exports.generateId = () => Math.floor(Math.random() * 9999);Test:
const { generateId } = require('./expenseId');
test('should mock random ID', () => {
jest.spyOn(Math, 'random').mockReturnValue(0.12345);
const id = generateId();
expect(id).toBe(1234);
Math.random.mockRestore();
});You just controlled randomness.
You are basically a magician now. āØ
š§© Step 4āāāMocking UserĀ Input
Letās pretend the user enters an expense:
š expenseInput.js
exports.parseInput = (input) => ({
amount: Number(input.amount),
note: input.note || "",
});Test:
test('should parse user input', () => {
const fakeInput = { amount: "400", note: "Snacks" };
const result = parseInput(fakeInput);
expect(result.amount).toBe(400);
expect(result.note).toBe("Snacks");
});Fake input.
Real confidence.
š§ Real-World Thought
Mocking data & events is not about taking shortcuts.
Itās about preserving your sanity.
If your tests rely on real user input or actual randomness, they will break randomly too.
Mocking removes uncertainty.
It removes noise.
It gives you focus.
Your tests stop being ātestsā and start being predictable simulations of your appās behavior.
ā Summary

Today,
Our Expense Tracker learned to handle fake data, fake events, and fake randomness like a pro.
Now we can:
 ⨠Mock user input
Ā āļø Mock events and listeners
Ā š² Control randomness
Ā š¾ Normalize and test messy data safely
Our tests are cleaner, predictable, and fun to write.
Next stop ā we push forward into mocking storage, caching, and persistent data layersāāāthe stuff that usually scares beginners.
š¬ Comment which part made you laugh (or cry) the mostāāāI read them all.
Thanks forĀ reading.
If this added value, follow me for more clear and practical posts.
ā Alkesh Jethava