Mocking Database Queries with Jest in TypeScript
Testing asynchronous operations, especially those involving database queries, can be tricky. Directly hitting a database during testing is slow, unreliable (dependent on external services), and can modify data. This challenge focuses on creating a mock for a function that executes a database query, allowing you to isolate and test the logic that uses the query results without actually interacting with a database.
Problem Description
You are tasked with creating a Jest mock for a function executeQuery which simulates a database query. This function takes a query string as input and returns a Promise that resolves to an array of objects representing the query results. Your goal is to create a mock implementation of executeQuery that you can use in your Jest tests to control the data returned by the query and verify that the function using executeQuery calls it with the expected query string.
Key Requirements:
- Mock Implementation: Create a mock function that mimics the behavior of
executeQuery. It should accept a query string as an argument and return a Promise. - Promise Resolution: The mock function's Promise should resolve to a predefined array of mock data.
- Query String Verification: The mock should allow you to verify that the query string passed to
executeQuerymatches the expected value. - TypeScript Compatibility: The solution must be written in TypeScript and adhere to TypeScript best practices.
Expected Behavior:
When the mock executeQuery is used in a test, it should:
- Resolve its Promise with a predefined array of mock data.
- Allow the test to assert that the query string passed to the mock matches the expected query string.
Edge Cases to Consider:
- The query string passed to
executeQuerymight be different in different test scenarios. - The mock should be easily configurable to return different mock data for different tests.
Examples
Example 1:
Input: `executeQuery("SELECT * FROM users")` within a test, with a mock configured to return `[{id: 1, name: "Alice"}]` and expect the query string "SELECT * FROM users"
Output: The test should pass, verifying that the query string matches and the Promise resolves with the mock data.
Explanation: The mock function is called with the specified query string, and the test asserts that the query string is correct and that the Promise resolves with the expected mock data.
Example 2:
Input: `executeQuery("SELECT * FROM products")` within a test, with a mock configured to return `[{id: 101, name: "Laptop"}]` and expect the query string "SELECT * FROM products"
Output: The test should pass, verifying that the query string matches and the Promise resolves with the mock data.
Explanation: Similar to Example 1, but with a different query string and mock data.
Example 3: (Edge Case)
Input: `executeQuery("SELECT * FROM orders WHERE status = 'pending'")` within a test, with a mock configured to return `[{id: 201, order_date: "2023-11-15"}]` and expect the query string "SELECT * FROM orders WHERE status = 'pending'"
Output: The test should pass, verifying that the query string matches and the Promise resolves with the mock data.
Explanation: Demonstrates that the mock can handle more complex query strings.
Constraints
- The mock function must be compatible with Jest's
jest.mock()andmockImplementation()functions. - The mock function must return a Promise.
- The mock data should be an array of objects.
- The solution should be concise and readable.
- The mock should be easily reusable across multiple tests.
Notes
Consider using jest.mock() to create the mock and mockImplementation() to define its behavior. Think about how to make the mock configurable so that different tests can use different mock data and query string expectations. Remember that the mock needs to return a Promise to accurately simulate an asynchronous database query. You don't need to implement the actual database logic; just focus on creating a mock that behaves like executeQuery.