Testing Asynchronous Functions with Async/Await in Jest (TypeScript)
Testing asynchronous code can be tricky, but Jest provides excellent tools for it. This challenge focuses on writing Jest tests using async/await to verify the behavior of asynchronous functions, ensuring your code handles promises correctly and behaves as expected under various conditions. Successfully completing this challenge demonstrates proficiency in testing asynchronous TypeScript code.
Problem Description
You are given a module containing an asynchronous function called fetchData. This function simulates fetching data from an API and returns a promise that resolves with a string. Your task is to write a Jest test suite using async/await to thoroughly test fetchData. The test suite should cover the following scenarios:
- Successful Fetch: Verify that
fetchDataresolves with the expected string when the API call is successful. - Error Handling: Verify that
fetchDatarejects with an error when the API call fails (simulated by throwing an error within the function). - Timeout Handling: Verify that
fetchDatarejects with a timeout error if the API call takes longer than a specified timeout duration.
Examples
Example 1: Successful Fetch
Input: fetchData() - successful API call
Output: "Data fetched successfully!"
Explanation: The function should resolve with the expected success message.
Example 2: Error Handling
Input: fetchData() - API call fails
Output: Error: "Failed to fetch data."
Explanation: The function should reject with an appropriate error message when the API call fails.
Example 3: Timeout Handling
Input: fetchData(500) - API call takes longer than 500ms
Output: Error: "Request timed out after 500ms."
Explanation: The function should reject with a timeout error if the API call exceeds the specified timeout.
Constraints
- The
fetchDatafunction accepts an optional timeout parameter (in milliseconds). If no timeout is provided, a default timeout of 200ms should be used. - The timeout should be enforced using
setTimeoutandPromise.race. - The error messages should be clear and descriptive.
- Your test suite should be well-structured and easy to understand.
- Use Jest's
expectassertions to verify the expected behavior.
Notes
- Consider using
try...catchblocks within yourasynctest functions to handle promise rejections gracefully. - Think about how to simulate both successful and failed API calls within the
fetchDatafunction for testing purposes. - The
fetchDatafunction is provided below. Do not modify thefetchDatafunction itself. Focus solely on writing the Jest tests. - You can use
jest.setTimeoutto adjust the default timeout for your tests if needed.
// fetchData.ts (Do not modify this file)
export async function fetchData(timeout?: number): Promise<string> {
const defaultTimeout = 200;
const actualTimeout = timeout || defaultTimeout;
return new Promise((resolve, reject) => {
setTimeout(() => {
const shouldFail = Math.random() < 0.3; // Simulate a 30% chance of failure
if (shouldFail) {
reject(new Error("Failed to fetch data."));
} else {
resolve("Data fetched successfully!");
}
}, actualTimeout);
});
}