Hone logo
Hone
Problems

Mocking Functions with jest.fn() in Jest

This challenge focuses on understanding and utilizing jest.fn() in Jest, a crucial tool for isolating units of code during testing. You'll be creating mock functions to replace dependencies within a module, allowing you to verify interactions and control the behavior of those dependencies without relying on their actual implementations. Mastering jest.fn() is essential for writing robust and maintainable tests.

Problem Description

You are tasked with creating a module called apiService that contains a function fetchData which is responsible for fetching data from an external API. For testing purposes, you don't want to actually make network requests. Instead, you need to mock the fetchData function using jest.fn() to control its return value and verify that it's called with the correct arguments.

Your goal is to write a Jest test that:

  1. Imports the apiService module.
  2. Uses jest.fn() to create a mock function.
  3. Replaces the original fetchData function in apiService with the mock function.
  4. Calls a function in apiService that uses fetchData.
  5. Asserts that the mock function was called with the expected arguments.
  6. Asserts that the function in apiService returns the value returned by the mock function.

Examples

Example 1:

// apiService.ts
export const fetchData = async (url: string): Promise<string> => {
  // In reality, this would make an API call
  return `Data from ${url}`;
};

export const processData = async (url: string): Promise<string> => {
  const data = await fetchData(url);
  return `Processed: ${data}`;
};

// test.ts
import * as apiService from './apiService';

describe('apiService', () => {
  it('should call fetchData with the correct URL and return processed data', async () => {
    const mockFetchData = jest.fn().mockResolvedValue('Mocked Data');
    apiService.fetchData = mockFetchData;

    const result = await apiService.processData('https://example.com');

    expect(mockFetchData).toHaveBeenCalledWith('https://example.com');
    expect(result).toBe('Processed: Mocked Data');
  });
});

Output: Test passes. Explanation: The mock function mockFetchData is called with the URL 'https://example.com', and processData returns 'Processed: Mocked Data' because mockFetchData returns 'Mocked Data'.

Example 2:

// apiService.ts (same as above)
// test.ts
import * as apiService from './apiService';

describe('apiService', () => {
  it('should handle fetchData errors', async () => {
    const mockFetchData = jest.fn().mockRejectedValue(new Error('API Error'));
    apiService.fetchData = mockFetchData;

    await expect(apiService.processData('https://example.com')).rejects.toThrow('API Error');
    expect(mockFetchData).toHaveBeenCalledWith('https://example.com');
  });
});

Output: Test passes. Explanation: The mock function mockFetchData is called with the URL 'https://example.com', and processData throws an error because mockFetchData is configured to reject with an error.

Constraints

  • The apiService.ts file will be provided as a starting point. You should not modify this file.
  • You must use jest.fn() to create the mock function.
  • The test should be written in TypeScript.
  • The mock function should be configured to resolve with a string value of "Mocked Data" initially.
  • The test should verify that the mock function is called with the correct URL.
  • The test should verify that the function in apiService returns the value returned by the mock function.

Notes

  • Consider using mockResolvedValue to easily configure the mock function to resolve with a specific value.
  • Think about how to replace the original function with the mock function before calling the function you want to test.
  • Remember to use toHaveBeenCalledWith to verify the arguments passed to the mock function.
  • You can extend the test to handle error scenarios by using mockRejectedValue and expect(...).rejects.toThrow().
Loading editor...
typescript