Hone logo
Hone
Problems

Manual Mock Implementation in Jest

This challenge focuses on understanding and implementing manual mocks in Jest. Manual mocks allow you to precisely control the behavior of dependencies within your unit tests, isolating the code under test and ensuring predictable results. This is crucial for testing components that rely on external services, modules, or functions.

Problem Description

You are tasked with creating a manual mock for a function called fetchData which is used within a module called apiService. The fetchData function is responsible for fetching data from an external API. Your goal is to create a Jest mock that allows you to control the data returned by fetchData during your tests, without actually making a network request.

Specifically, you need to:

  1. Create a mock implementation of fetchData that accepts a URL as an argument.
  2. The mock should allow you to specify a response object to return when called. This response object should have a json method that resolves to a specified mockData (also provided by the test).
  3. The mock should be applied to the apiService module before the module is imported into the component being tested.
  4. Write a test case that uses the mock to verify that a component correctly handles a specific response from fetchData.

Examples

Example 1:

Input:
apiService.ts:
export const fetchData = async (url: string): Promise<any> => {
  const response = await fetch(url);
  return response.json();
};

Component.ts:
import { fetchData } from './apiService';

export const Component = async () => {
  const data = await fetchData('https://example.com/data');
  return `Data: ${data.message}`;
};

Test.test.ts:
// Test file
// Expected Output (in test):
// "Data: Mocked Message"

Explanation: The test should mock fetchData to return a response object with a json method that resolves to { message: 'Mocked Message' }. The component should then render "Data: Mocked Message".

Example 2:

Input:
apiService.ts:
export const fetchData = async (url: string): Promise<any> => {
  const response = await fetch(url);
  return response.json();
};

Component.ts:
import { fetchData } from './apiService';

export const Component = async () => {
  const data = await fetchData('https://example.com/data');
  if (data.success) {
    return `Success: ${data.result}`;
  } else {
    return `Error: ${data.error}`;
  }
};

Test.test.ts:
// Test file
// Expected Output (in test):
// "Error: Mocked Error"

Explanation: The test should mock fetchData to return a response object with a json method that resolves to { success: false, error: 'Mocked Error' }. The component should then render "Error: Mocked Error".

Constraints

  • The mock must be implemented manually using jest.fn() and not rely on jest.mock() with auto-mocking.
  • The fetchData function is asynchronous and returns a Promise. Your mock must also return a Promise.
  • The mock must be applied before the apiService module is imported into the component being tested.
  • The test should use async/await for clarity.
  • The mock should accept a URL argument, but the URL itself is not important for the test; only the returned data matters.

Notes

  • Consider how to create a response object that mimics the behavior of the actual fetch API. Remember that fetch returns a Response object, which has a json() method.
  • Think about how to use jest.fn() to create a mock function and how to control its return value.
  • This exercise is about understanding the fundamentals of manual mocking. Focus on creating a clear and controllable mock, rather than complex logic within the mock itself.
  • The mockData should be a simple JavaScript object.
Loading editor...
typescript