MockReturnValue is not a function usually means you’re calling mockReturnValue() on something that isn’t a Jest mock yet.
What This Error Is Telling You
You only get mockReturnValue() when the thing you’re calling is a Jest mock function. If it’s a real function, a class method, a getter, or a value that got imported in a way Jest can’t replace, the method won’t exist and the test blows up.
This message shows up most often when a mock didn’t apply, a spy was created on the wrong object, or a TypeScript type made you think a value was mocked when it wasn’t.
One detail trips people up. Your editor can autocomplete mockReturnValue because of a type cast, then runtime disagrees. That’s when you see mockreturnvalue is not a function and it feels like Jest is lying. It isn’t. Your value just never became a mock.
Most fixes take two minutes.
Fast Clues From The Stack Trace
Don’t scroll past the first “at” line. It usually points to the call site where you assumed a mock. If the line is inside your test file, your setup is wrong. If the line is inside a helper, your helper is importing a real dependency and returning it unchanged.
- Confirm The Target Is A Mock — Check it has methods like
mockImplementationand amockproperty. - Check Import Style — Default vs named imports can change what you actually received.
- Check The Mock Timing — Mocks must be set up before the module under test is imported.
MockReturnValue Is Not A Function Error In Jest Tests
This is the quickest way to locate the exact mismatch. Start by answering one question. What is the value at runtime on the line where you call mockReturnValue()?
Run A Tiny Reality Check
Drop this once, run the test, then remove it.
console.log(typeof myThing, myThing);
console.log("has mockReturnValue", !!myThing?.mockReturnValue);
If has mockReturnValue is false, the fix is not “add another cast”. The fix is to turn that target into a Jest mock, or switch to the right mocking tool for that target.
Spot The Two Classic Traps
- Mocking A Local Copy — You mocked one reference, then your code called another reference that still points to the real function.
- Mocking A Value, Not A Function — Your import is a constant, object, or class instance, so
mockReturnValue()can’t apply.
Check For Duplicate Imports
In larger codebases, the same module can be imported through two paths, like "@/auth" and "../auth". You mock one path, your code uses the other, and the mock never touches it.
- Align Import Paths — Pick one alias or one relative style and stick with it across the project.
Fixes For Common Mock Targets
The right fix depends on what you are mocking. The table below matches common targets to the Jest tool that fits.
| What You’re Mocking | Best Jest Tool | Why It Works |
|---|---|---|
| Plain function you call directly | jest.fn() |
Creates a mock with mockReturnValue(). |
| Imported module function | jest.mock() |
Replaces the module export before import time. |
| Method on an object | jest.spyOn() |
Wraps the real method with a spy you can stub. |
| Getter property | jest.spyOn(obj, "x", "get") |
Getters need a getter spy, not a function mock. |
| Default export module | jest.mock() + default |
Default exports often need a default key in the mock. |
Fix A Plain Function
If the function is passed in or created in your test, make it a mock from the start.
const getToken = jest.fn();
getToken.mockReturnValue("abc");
expect(getToken()).toBe("abc");
- Prefer One Source Of Truth — Pass the mock into the unit under test instead of importing a real function and trying to replace it later.
Fix An Imported Named Export
If your code imports a module function, mock that module and return a mocked export. Put the jest.mock() call at the top level so it runs before imports are evaluated.
// auth.ts
export const readSession = () => "real";
// auth.test.ts
jest.mock("./auth", () => ({
readSession: jest.fn(),
}));
import { readSession } from "./auth";
(readSession as jest.Mock).mockReturnValue("fake");
If you still get the error, you may be importing the function into your code and re-exporting it, then mocking only one layer. In that setup, mock the layer your unit actually imports, not the original source file.
- Keep The Mock Shape Accurate — The keys in the factory must match the real export names.
- Avoid Re-Importing Inside Tests — Import once; reset modules only when you truly need isolation.
Fix A Default Export
Default exports are a frequent source of confusion, since the mocked value often lives under a default property.
// client.ts
export default function client() { return "real"; }
// client.test.ts
jest.mock("./client", () => ({
__esModule: true,
default: jest.fn(),
}));
import client from "./client";
(client as jest.Mock).mockReturnValue("fake");
- Set __esModule For ESM Interop — This helps Jest treat the factory like an ES module.
- Return The Same Kind Of Value — If the real default export is a function, mock it as a function, not an object.
Fix A Method On An Object
If your code calls obj.method(), you don’t replace obj. You spy on the method.
const api = {
fetchUser: () => ({ id: 1 }),
};
jest.spyOn(api, "fetchUser").mockReturnValue({ id: 2 });
expect(api.fetchUser().id).toBe(2);
This pattern is also the clean fix for libraries like axios when you import a default instance and call axios.get. Spy on the method you call, stub the return, then restore it.
- Restore After Each Test — Use
mockRestore()orjest.restoreAllMocks()to avoid cross-test leakage.
Fix A Getter
When the code reads a property that is backed by a getter, you must spy on the getter.
const settings = {
get region() {
return "us";
},
};
jest.spyOn(settings, "region", "get").mockReturnValue("eu");
- Don’t Treat Getters Like Functions — A getter spy is the path that gives you stubbing methods.
Fix Async Returns Without Fighting Promises
If the real function returns a promise, don’t return a raw value and hope it works. Use mockResolvedValue so the call site sees the same shape.
const fetchUser = jest.fn();
fetchUser.mockResolvedValue({ id: 1 });
await expect(fetchUser()).resolves.toEqual({ id: 1 });
- Match The Real Contract — Promise in production, promise in tests.
TypeScript And ESM Gotchas That Trigger The Error
TypeScript can hide the real issue because a cast can silence the compiler while the runtime value stays unchanged. If you see yourself writing as unknown as jest.Mock to make the crash stop, take a beat and verify the mock applied.
Use Jest Helpers Instead Of Risky Casts
Jest ships helpers that keep the type close to the runtime truth.
import { readSession } from "./auth";
const readSessionMock = jest.mocked(readSession);
readSessionMock.mockReturnValue("fake");
- Let Types Follow Runtime — If
jest.mocked()can’t type it, that’s a hint your setup is off.
Mind Hoisting And Module Cache
Jest hoists jest.mock() calls, but only when they are at the top level. If you call jest.mock() inside a test block, it can be too late because the real module is already loaded.
- Mock Before Import — Keep mocks near the top of the file, above imports of the unit under test.
- Reset Modules Sparingly —
jest.resetModules()can help when you need a fresh import, but it can slow the suite and hide design issues.
ESM Projects Need A Different Hook Sometimes
With native ESM in Jest, mocking can shift toward jest.unstable_mockModule and dynamic import. If you’re on ESM and a normal factory mock never applies, check your Jest version and config, then follow the ESM mocking path for your setup.
- Prefer One Module System — Mixed CommonJS and ESM imports are where many “it looks mocked” bugs are born.
A Step-By-Step Debug Flow That Works Fast
If you want a repeatable path, run this flow in order. It’s short, but it catches most real-world cases.
- Identify The Exact Target — Point at the variable you call
mockReturnValue()on and trace where it came from. - Check Runtime Shape — Verify it has
mockReturnValueand amockproperty when printed. - Pick The Correct Tool — Use
jest.fnfor plain functions,jest.mockfor module exports,jest.spyOnfor methods. - Place The Setup Early — Put mocks at top level so they run before imports.
- Clear Prior State — Use
jest.clearAllMocks()inafterEachwhen you reuse mocks across tests.
Two Checks That Reveal Most Mistakes
// if this is false, your value isn't a Jest mock
expect(jest.isMockFunction(myThing)).toBe(true);
// if this prints the real function body, your mock did not apply
console.log(myThing.toString());
Patterns That Prevent Mock Failures Next Time
This is where you can save hours across a codebase. The goal is to make mocking boring and predictable, so the crash never shows up again.
Design For Injection In Small Units
If a module reads globals or imports concrete dependencies, mocking gets brittle. If a function accepts its dependencies as arguments, tests can pass mocks directly and skip tricky module replacement.
// production
export const makeService = (readSession) => ({
load: () => readSession(),
});
// test
const readSession = jest.fn().mockReturnValue("fake");
const svc = makeService(readSession);
expect(svc.load()).toBe("fake");
- Keep Dependencies Explicit — It makes tests smaller and failures easier to spot.
Centralize Mock Builders
If many tests need the same mock shape, create a small helper that returns mocks with safe defaults. This reduces copy-paste errors and keeps the mock shape aligned with the real module.
export const makeAuthMocks = () => ({
readSession: jest.fn().mockReturnValue("fake"),
});
- Use One Factory Per Module — Tests stay consistent, and the mocks stay readable.
Use A Clean Teardown
Leaky spies can cause the next test to fail in ways that look unrelated. A simple teardown policy keeps the suite steady.
afterEach(() => {
jest.restoreAllMocks();
jest.clearAllMocks();
});
- Restore Spies — Spies change real objects; restoring resets them back.
- Clear Call History — Clearing keeps assertion noise out of later tests.
Keep A Final Checklist In The File
If you’ve hit this once, you’ll hit it again. Pin a checklist near the bottom of the test file so anyone can self-serve the fix. When you see mockreturnvalue is not a function, run these items in order.
- Confirm The Value Is A Mock —
jest.isMockFunction(x)should be true. - Confirm You Mocked The Right Reference — The code under test must call the same export or method you mocked.
- Confirm Mock Setup Runs First — Move
jest.mockabove the import that uses it. - Swap Tool If Needed — If it’s a method or getter, use a spy, not
jest.fn. - Remove Risky Casts — Casts can hide the mismatch and waste time.
- Match Sync Vs Async — Use
mockResolvedValuefor promise returns.
Once the target is a real Jest mock, mockReturnValue() will exist, your stubs will stick, and the error goes away. If it keeps popping up, it’s a sign your test is fighting your module boundaries, not a sign you need more clever mocking tricks.
