Hone logo
Hone
Problems

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:

  1. Mock userService: Create a mock implementation of userService with a predefined set of users.
  2. Implement getUserById: The mock userService.getUserById method should correctly return a User object for valid, existing IDs, and null for non-existent or invalid IDs.
  3. Use test.each: Utilize Jest's test.each to define multiple test cases for the getUserById method.
  4. 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).
  5. Assertion: Assert that the correct User object or null is 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 userService should be sufficient for testing the getUserById method.
  • The test suite must use Jest's test.each to 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.each data. 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.each for parameterizing tests. You can also explore creating more advanced custom test providers if you're feeling adventurous, but using test.each is the primary goal.
  • Ensure your tests are clear and the descriptions accurately reflect the scenario being tested.
Loading editor...
typescript