Node.js TypeScript中Jest单元测试Mock findById方法失败求助
Hey there! Let's break down what's going wrong here and fix your test step by step.
First, let's address the immediate error
Looking at your test output, the received value is a Promise {} instead of your expected orderModel. That's because your FindById method is async—when you call it without await, it returns a Promise object, not the resolved value. That's the biggest reason your test is failing.
Next, let's fix the mock and service setup issues
Your current test uses uninitialized orderRepository and logger variables, which can lead to unexpected behavior. Plus, mocking the prototype directly works but isn't the cleanest approach for TypeScript. Let's rewrite the test with proper mocks and setup.
Here's the corrected test code:
import OrderService from '../src/services/order'; import { OrderRepository } from '../src/repository/orderRepository'; import Order from '../src/models/order'; const orderData = {id_product: "564sd654asd5as64d", quantity: 3, orderStatus: "registeredOrder", deliveryDateResquested: "2019-12-25"}; const orderModel = new Order(orderData); describe('Order', () => { let orderService: OrderService; let mockOrderRepository: jest.Mocked<OrderRepository>; let mockLogger: { error: jest.Mock }; // Initialize fresh mocks and service before each test beforeEach(() => { // Create a mocked logger (since your service expects it) mockLogger = { error: jest.fn() }; // Create a mocked OrderRepository with pre-configured findById mockOrderRepository = { findById: jest.fn().mockResolvedValue(orderModel) } as jest.Mocked<OrderRepository>; // Instantiate the service with our mocked dependencies orderService = new OrderService(mockOrderRepository, mockLogger); }); test('FindById should return the correct order', async () => { // Await the async method to get the resolved value const result = await orderService.FindById("cenas"); // Use toEqual for deep object comparison (toBe checks exact references) expect(result).toEqual(orderModel); // Verify the repository method was called correctly (good practice!) expect(mockOrderRepository.findById).toHaveBeenCalledTimes(1); expect(mockOrderRepository.findById).toHaveBeenCalledWith("cenas"); }); });
Key changes explained:
- Added
awaitto theFindByIdcall: SinceFindByIdis async, it returns a Promise. Usingawaitresolves this Promise to get the actual order object. - Proper mocked dependencies: We create explicit mocks for
OrderRepositoryandloggerinstead of using uninitialized variables. This makes the test self-contained. - Used
mockResolvedValue: For async methods likefindById, we need to mock a resolved Promise (not just return the object directly). - Swapped
toBewithtoEqual: For object comparisons,toEqualchecks for deep equality, which is what you want when comparing two instances ofOrder. - Added mock call assertions: These ensure your service is actually interacting with the repository as expected, making your test more robust.
If you want to use TypeDI's Container in tests
If you prefer to use TypeDI's dependency injection instead of manually constructing the service, make sure to reset the Container and register your mocks before each test:
import { Container } from 'typedi'; // ... (keep imports and orderData/orderModel) describe('Order', () => { let orderService: OrderService; beforeEach(() => { Container.reset(); // Clear any existing dependencies // Register mocked logger Container.set('logger', { error: jest.fn() }); // Register mocked OrderRepository const mockRepo = { findById: jest.fn().mockResolvedValue(orderModel) }; Container.set(OrderRepository, mockRepo); // Get the service from the Container orderService = Container.get(OrderService); }); test('FindById should return the correct order', async () => { const result = await orderService.FindById("cenas"); expect(result).toEqual(orderModel); }); });
This approach keeps your test aligned with how your service is used in production, while still maintaining control over dependencies.
内容的提问来源于stack exchange,提问作者André Silva - PT

