Mocking a Module with jest.mock in TypeScript
This challenge focuses on using jest.mock in Jest to isolate and control the behavior of a module during testing. Mocking is a crucial technique for unit testing, allowing you to replace dependencies with controlled substitutes, preventing external factors from influencing your tests and ensuring focused verification of the code under test. You'll be mocking a simple utility module and verifying that your tests interact with the mock instead of the original implementation.
Problem Description
You are tasked with writing a unit test for a function processData that relies on a utility module dataFetcher.ts. The dataFetcher.ts module contains a function fetchData which simulates fetching data from an external source (e.g., an API). Your goal is to mock the fetchData function using jest.mock to control the data returned and verify that processData correctly handles the mocked data.
What needs to be achieved:
- Create a
dataFetcher.tsmodule with afetchDatafunction that returns a Promise resolving to a string. - Create a
processor.tsmodule with aprocessDatafunction that callsfetchDataand processes the returned string. - Write a Jest test for
processDatathat usesjest.mock('dataFetcher')to mock thefetchDatafunction. - Within the test, configure the mock implementation of
fetchDatato return a specific string. - Assert that
processDatareturns the expected result based on the mocked data.
Key Requirements:
- Use
jest.mockto mock the entiredataFetchermodule. - Provide a mock implementation for the
fetchDatafunction within thejest.mockcall. - Ensure the test verifies the behavior of
processDatawith the mocked data, not the originalfetchData. - The mock implementation should return a Promise that resolves to a string.
Expected Behavior:
When the test runs, processData should call the mocked fetchData function. The mock should return the string specified in the test. processData should then process this string and return a value that can be asserted in the test.
Edge Cases to Consider:
- Ensure the mock implementation returns a Promise, as the original
fetchDatadoes. - Verify that the mock is correctly applied and that the original
fetchDatais not called during the test.
Examples
Example 1:
// dataFetcher.ts
export async function fetchData(): Promise<string> {
return "Original Data";
}
// processor.ts
import { fetchData } from './dataFetcher';
export async function processData(): Promise<string> {
const data = await fetchData();
return `Processed: ${data}`;
}
// processor.test.ts
import { processData } from './processor';
import { fetchData } from './dataFetcher';
jest.mock('./dataFetcher');
describe('processData', () => {
it('should process mocked data', async () => {
(fetchData as jest.Mock).mockResolvedValue('Mocked Data');
const result = await processData();
expect(result).toBe('Processed: Mocked Data');
expect(fetchData).toHaveBeenCalledTimes(1); // Verify fetchData was called
});
});
Output: Test passes, asserting that processData returns "Processed: Mocked Data" and that fetchData was called once.
Explanation: The test mocks dataFetcher, sets the mock implementation of fetchData to return "Mocked Data", and then asserts that processData returns the expected processed string.
Constraints
- The
fetchDatafunction indataFetcher.tsmust return a Promise resolving to a string. - The mock implementation in the test must also return a Promise resolving to a string.
- The test should only mock the
dataFetchermodule, not individual functions within it (for simplicity). - The test should be written in TypeScript.
Notes
jest.mockhoists the mock implementation to the top of the file, so ensure your mock implementation is defined before you use it.- You can access the mock implementation using
(fetchData as jest.Mock).mockImplementation(...). - Consider using
mockResolvedValuefor simpler Promise-returning mocks. - Use
expect(fetchData).toHaveBeenCalledTimes(1)to verify that the mocked function was actually called during the test. This helps confirm that the mocking is working as expected.