Hone logo
Hone
Problems

Testing API Interactions with WireMock and Jest

This challenge focuses on using WireMock to mock an external API and Jest to test a function that interacts with that API. Mocking external dependencies is crucial for isolated unit testing, ensuring your code behaves as expected regardless of the availability or behavior of external services. You'll implement a Jest test suite that leverages WireMock to simulate API responses and verify the correct behavior of a function that consumes those responses.

Problem Description

You are tasked with creating a Jest test suite for a function called fetchUserData which retrieves user data from a hypothetical API endpoint /users/{userId}. The API is external and unreliable, so you need to mock it using WireMock. Your test suite should:

  1. Start WireMock: Before each test, start a WireMock server on a specified port (e.g., 8080).
  2. Configure WireMock: Configure WireMock to respond to requests to /users/{userId} with a predefined JSON response based on the userId provided in the request. You'll need to define at least two different responses for different user IDs.
  3. Implement fetchUserData: The fetchUserData function takes a userId as input and makes a GET request to the WireMock server to retrieve user data. It parses the JSON response and returns a UserData object.
  4. Write Jest Tests: Write at least two Jest tests that:
    • Verify that fetchUserData correctly parses the JSON response from WireMock for a specific userId.
    • Verify that fetchUserData handles a scenario where WireMock returns an error (e.g., a 500 status code). You'll need to configure WireMock to simulate this error for a specific userId.
  5. Stop WireMock: After each test, stop the WireMock server.

Expected Behavior:

  • The Jest tests should pass when WireMock is configured correctly and the fetchUserData function behaves as expected.
  • The tests should fail if WireMock is not started, configured incorrectly, or if fetchUserData does not handle the API responses correctly.
  • The tests should be isolated and not dependent on the actual API.

Interface:

interface UserData {
  id: number;
  name: string;
  email: string;
}

async function fetchUserData(userId: number): Promise<UserData> {
  // Implementation is not provided - you need to write this.
  // It should make a GET request to WireMock and parse the JSON response.
  throw new Error("fetchUserData not implemented");
}

Examples

Example 1:

Input: userId = 1
WireMock Response: { "id": 1, "name": "John Doe", "email": "john.doe@example.com" }
Output: { id: 1, name: 'John Doe', email: 'john.doe@example.com' }
Explanation: fetchUserData makes a request to WireMock for user ID 1, WireMock returns the specified JSON, and fetchUserData parses and returns the UserData object.

Example 2:

Input: userId = 2
WireMock Response: { "id": 2, "name": "Jane Smith", "email": "jane.smith@example.com" }
Output: { id: 2, name: 'Jane Smith', email: 'jane.smith@example.com' }
Explanation: Similar to Example 1, but for a different user ID and response.

Example 3:

Input: userId = 3
WireMock Response: HTTP Status Code: 500 Internal Server Error
Output: Jest test should throw an error indicating that fetchUserData failed to handle the error.
Explanation: fetchUserData makes a request to WireMock for user ID 3, WireMock returns a 500 error, and fetchUserData should handle this error gracefully (e.g., by throwing an exception or returning an error object).

Constraints

  • WireMock should be started and stopped before and after each test.
  • The WireMock server should run on port 8080.
  • The fetchUserData function should be asynchronous.
  • The Jest tests should use async/await for asynchronous operations.
  • You are allowed to use any reasonable Jest matchers.
  • The fetchUserData function should not contain any hardcoded API endpoints. It should use the userId parameter to construct the URL.

Notes

  • You'll need to install the necessary dependencies: jest, @types/jest, wiremock-node.
  • Consider using a library like node-fetch or the built-in fetch API to make HTTP requests.
  • Think about how to handle potential errors during the API request and response parsing.
  • The WireMock configuration can be done programmatically within the test suite.
  • Focus on writing clean, readable, and maintainable code. Proper error handling is important.
  • Remember to clean up WireMock after each test to avoid conflicts.
Loading editor...
typescript