class TempTool {
constructor() {
this.data = [];
}
add(item) {
this.data.push(item);
}
listAll() {
return this.data;
}
}
export default { instance: new TempTool() };
- Shared state across imports β One test modifying state affects all subsequent tests.
- Difficult to reset state β Requires manual instance resets.
- Mocking is harder β Singleton is instantiated before tests, making it difficult to override.
- Same input β Always same output
- No side effects
- Easier to test and debug
function add(a, b) {
return a + b;
}
console.log(add(5, 4)); // 9
console.log(add(5, 4)); // 9
console.log(add(5, 4)); // 9
module.exports = { add };
const { add } = require("./demo");
describe("Add function", () => {
it("adds two inputs", () => {
expect(add(4, 5)).toEqual(9);
});
});
function add(a, b) {
return a + b + Math.random();
}
const { add } = require("./demo");
describe("Add function", () => {
it("adds two inputs", () => {
const output = add(4, 5);
expect(output).toEqual(); // β What is the expected output?
});
});
const { add } = require("./demo");
describe("Add function", () => {
it("adds two inputs", () => {
jest.spyOn(Math, "random").mockImplementation(() => 10);
const output = add(4, 5);
expect(output).toEqual(19);
});
});
β Avoid Singletons β They introduce shared state issues and make testing difficult.
β Use Pure Functions β They make your code more predictable and testable.
β Mock Impure Functions β When external dependencies exist, mock them to create repeatable results.