Jest Test Provider Implementation
This challenge focuses on enhancing your Jest testing capabilities by implementing custom test providers. Test providers are a powerful feature in Jest that allow you to generate multiple test cases from a single test definition, making your test suites more concise and maintainable, especially when dealing with variations of inputs and expected outputs.
Problem Description
Your task is to create a Jest test suite for a hypothetical userService that has a method getUserById(userId: number): User | null. This method can return a User object or null if the user is not found. You will use Jest's test.each (or a custom test provider if you want to go beyond the basic functionality) to dynamically generate tests for various userId inputs, including valid IDs, invalid IDs (non-numeric or negative), and IDs that do not exist in your mock data.
Key Requirements:
- Mock
userService: Create a mock implementation ofuserServicewith a predefined set of users. - Implement
getUserById: The mockuserService.getUserByIdmethod should correctly return aUserobject for valid, existing IDs, andnullfor non-existent or invalid IDs. - Use
test.each: Utilize Jest'stest.eachto define multiple test cases for thegetUserByIdmethod. - Test Scenarios: Cover at least the following scenarios:
- Valid user ID that exists.
- Valid user ID that does not exist.
- Invalid user ID (e.g., negative number).
- Invalid user ID (e.g., string).
- Assertion: Assert that the correct
Userobject ornullis returned for each scenario.
Expected Behavior:
The tests should pass when the userService.getUserById method behaves as expected across all defined scenarios.
Edge Cases:
- Handling of non-numeric
userId. - Handling of negative
userId. - Empty user list in the mock service.
Examples
Let's define a simple User interface and some mock data.
interface User {
id: number;
name: string;
email: string;
}
const mockUsers: User[] = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
];
class MockUserService {
getUserById(userId: number): User | null {
if (typeof userId !== 'number' || userId <= 0) {
return null; // Handle invalid input types or non-positive numbers
}
const user = mockUsers.find(user => user.id === userId);
return user || null;
}
}
Example 1: Valid User ID (Exists)
Input: userId = 1
Expected Output: { id: 1, name: 'Alice', email: 'alice@example.com' }
Example 2: Valid User ID (Does Not Exist)
Input: userId = 3
Expected Output: null
Example 3: Invalid User ID (Negative)
Input: userId = -5
Expected Output: null
Example 4: Invalid User ID (String)
Input: userId = 'abc'
Expected Output: null (Note: While the type signature is number, Jest might pass unexpected types in less strict scenarios. A robust implementation should handle this, or your tests can focus on valid types if that's the intended scope.)
Constraints
- Your mock
userServiceshould be sufficient for testing thegetUserByIdmethod. - The test suite must use Jest's
test.eachto iterate over test cases. - You should provide at least four distinct test cases covering the scenarios described in the Problem Description.
Notes
- Consider how you will structure your
test.eachdata. A common pattern is an array of arrays or an array of objects. - Think about how to represent the expected output, especially when it's
null. - This challenge is designed to familiarize you with
test.eachfor parameterizing tests. You can also explore creating more advanced custom test providers if you're feeling adventurous, but usingtest.eachis the primary goal. - Ensure your tests are clear and the descriptions accurately reflect the scenario being tested.