I am testing a function using Jest that calls an asynchronous function. The function seems to be called as verified by console logs, but Jest’s spy is not detecting the call. Here are the relevant code snippets:
export async function handleExcessQuantityScenario({
productTrackeId,
matchingRemainingProducts,
points,
company,
transaction,
}) {
console.log("handleExcessQuantityScenario called", {
productTrackeId,
matchingRemainingProducts,
points,
company,
transaction,
});
for (const matchingRemainingProduct of matchingRemainingProducts) {
const productTracker = await strapiApi.getProductTracker(productTrackeId);
const currProductsQuantitySum =
matchingRemainingProduct.quantity + productTracker.quantity;
if (currProductsQuantitySum > productTracker.requiredQuantity) {
await handleProductExcess(
productTracker,
matchingRemainingProduct,
points,
company,
transaction,
currProductsQuantitySum
);
} else if (currProductsQuantitySum === productTracker.requiredQuantity) {
await handleExactProductMatch(
productTracker,
matchingRemainingProduct,
points,
company,
transaction
);
} else {
await handleInsufficientMatchSenario({
productTracker: productTracker,
totalQuantity: matchingRemainingProduct.quantity,
productsToConnect: [matchingRemainingProduct],
});
}
}
}
**Test code : **
import { processMatchingRemainingProducts } from "../../lib/transaction/processProductTrackers";
import * as transactionUtils from "../../lib/transaction/processProductTrackers";
import strapiApi from "../../lib/api";
import { adjustCompanyPoints } from "../../lib/transaction/utils";
jest.mock("../../lib/api");
jest.mock("../../lib/transaction/utils");
jest.mock("../../lib/transaction/processProductTrackers", () => {
const originalModule = jest.requireActual("../../lib/transaction/processProductTrackers");
return {
__esModule: true,
...originalModule,
handleExcessQuantityScenario: jest.fn(),
};
});
describe("processProductTrackers", () => {
const mockProductTracker = {
id: 1,
name: "Test Product Tracker",
requiredQuantity: 10,
quantity: 5,
points: 10,
brand: { id: 1, name: "Test Brand" },
productRange: { id: 1 },
remainingProducts: [],
company: { id: 1, currentPoints: 5, totalPoints: 110 },
};
const mockRemainingProduct = {
id: 1,
quantity: 6,
product: {
id: 1,
brand: { id: 1, name: "Test Brand" },
range: { id: 1, name: "Test Range" },
},
};
const mockCompany = { id: 1, currentPoints: 5, totalPoints: 110 };
const mockTransaction = { id: 1 };
beforeEach(() => {
jest.resetAllMocks();
jest.spyOn(strapiApi, "updateProductTracker").mockResolvedValue(Promise.resolve() as any);
jest.spyOn(strapiApi, "createClaimedRemainingProduct").mockResolvedValue(Promise.resolve() as any);
jest.spyOn(strapiApi, "getProductTracker").mockResolvedValue(mockProductTracker as any);
jest.spyOn(strapiApi, "updateRemainingProduct").mockResolvedValue(Promise.resolve() as any);
jest.spyOn(strapiApi, "createRemainingProduct").mockResolvedValue({ id: 2 } as any);
jest.spyOn(strapiApi, "updateRemainingProducts").mockResolvedValue(Promise.resolve() as any);
(adjustCompanyPoints as jest.Mock).mockResolvedValue(Promise.resolve());
});
it("should handle excess quantity scenario when total quantity exceeds required quantity", async () => {
const matchingRemainingProducts = [
{ ...mockRemainingProduct, quantity: 6 },
];
const handleExcessQuantityScenarioMock = jest.spyOn(
transactionUtils,
"handleExcessQuantityScenario"
);
await processMatchingRemainingProducts(
mockProductTracker,
matchingRemainingProducts,
mockCompany,
mockTransaction
);
expect(handleExcessQuantityScenarioMock).toHaveBeenCalled();
expect(handleExcessQuantityScenarioMock).toHaveBeenCalledWith({
productTrackeId: mockProductTracker.id,
matchingRemainingProducts,
points: mockProductTracker.points,
company: mockCompany,
transaction: mockTransaction,
});
});
});
Test Output:
console.log
handleExcessQuantityScenario called {
productTrackeId: 1,
matchingRemainingProducts: [ { id: 1, quantity: 6, product: [Object] } ],
points: 10,
company: { id: 1, currentPoints: 5, totalPoints: 110 },
transaction: { id: 1 }
}
at handleExcessQuantityScenario (lib/transaction/processProductTrackers.ts:142:13)
FAIL src/__tests__/transaction/processProductTrackers.spec.ts
processProductTrackers
✓ should find all matches between product tracker and transaction remaining products and process them (1 ms)
✓ should handle product trackers with no remaining products
✕ should handle excess quantity scenario when total quantity exceeds required quantity (14 ms)
● processProductTrackers › should handle excess quantity scenario when total quantity exceeds required quantity
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
174 | );
175 |
> 176 | expect(handleExcessQuantityScenarioMock).toHaveBeenCalled();
Summary:
The handleExcessQuantityScenario function is confirmed to be called based on the console log, but Jest’s spy is not detecting the call. All promises in the source code and test are awaited. The function is correctly mocked, and the spy is set up using jest.spyOn. Despite this, the test fails, indicating the spy has not detected any calls. How can I ensure that Jest correctly tracks the call to the handleExcessQuantityScenario function?
I have a function handleExcessQuantityScenario that is called within processMatchingRemainingProducts. In my Jest test, I use jest.spyOn to spy on handleExcessQuantityScenario. Despite seeing console logs indicating that the function is called, the spy is not detecting the call. I expect the spy to detect the function call and pass the test. However, the test fails with “Expected number of calls: >= 1, Received number of calls: 0”.