Jest Manual Mocking for API Service
This challenge focuses on creating manual mocks for external API services in Jest. Unit testing often requires isolating the code under test from its dependencies, such as network requests or database interactions. By manually mocking these dependencies, we can control their behavior and ensure our tests are reliable and fast.
Problem Description
You are tasked with testing a UserService class that depends on an external ApiService. The ApiService is responsible for making HTTP requests to fetch user data. Your goal is to write Jest tests for UserService without actually making real HTTP requests. To achieve this, you will create a manual mock for the ApiService.
The UserService class has a method getUserDetails(userId: string) which calls ApiService.get(/users/${userId}).
Your task involves:
- Creating a manual mock for the
ApiServicemodule. - Configuring the mock to simulate different API responses (e.g., successful user retrieval, user not found, network error).
- Writing Jest tests for the
UserService.getUserDetailsmethod using the mockedApiService.
Examples
Example 1: Successful User Retrieval
- Scenario: The
ApiServicesuccessfully returns user data for a givenuserId. - Input to Test:
userService.getUserDetails('123') - Mocked
ApiService.getBehavior: Resolves with a promise containing user data:{ "id": "123", "name": "Alice", "email": "alice@example.com" } - Expected Output from
userService.getUserDetails('123'):Promise<{ id: string; name: string; email: string }> // Resolved with the user data - Explanation: The
UserServicesuccessfully fetches and returns the user details by leveraging the mockedApiService.
Example 2: User Not Found
- Scenario: The
ApiServicereturns a 404 Not Found error. - Input to Test:
userService.getUserDetails('456') - Mocked
ApiService.getBehavior: Rejects with an error object simulating a 404:new Error("User with ID 456 not found."); // Or a more specific error structure - Expected Output from
userService.getUserDetails('456'):Promise<null | undefined> // Or a specific error thrown by UserService - Explanation: The
UserServiceshould handle the "not found" scenario gracefully, perhaps by returningnullorundefined, or by re-throwing a more specific error.
Example 3: Network Error
- Scenario: The
ApiServiceencounters a network error during the request. - Input to Test:
userService.getUserDetails('789') - Mocked
ApiService.getBehavior: Rejects with a generic network error:new Error("Network error."); - Expected Output from
userService.getUserDetails('789'):Promise<null | undefined> // Or a specific error thrown by UserService - Explanation: The
UserServiceshould catch network errors and handle them appropriately, potentially returningnullorundefined, or re-throwing a custom error.
Constraints
- The
ApiServiceis assumed to be an external module that you cannot modify. - Your solution must use Jest's manual mocking capabilities.
- Tests should be written in TypeScript.
- The mocked
ApiServiceshould have agetmethod that returns aPromise.
Notes
- Consider how to reset the mock's behavior between different test cases.
- Think about how you will assert that the
ApiService.getmethod was called with the correct URL. - You will likely need to create a
__mocks__directory for yourApiService. - The structure of the
ApiServiceandUserServicewill be provided, but you will need to implement the mocks and tests.