如何使用Jest模拟类构造函数中的startEngine箭头方法并验证调用?
startEngine is called in the Car constructor Got it, let's break this down. The issue here is that your startEngine is defined as a class field arrow function—these are bound directly to each instance of Car, not attached to the Car.prototype. That's why trying to access Car.prototype.startEngine returns undefined and your prototype-based mock doesn't work.
Here are two straightforward ways to test that startEngine gets called during instantiation:
Method 1: Create a Test Subclass (Cleanest Approach)
The simplest way is to extend your Car class and override the startEngine field with a mock/spy function. When you instantiate this subclass, the constructor will call your mock instead of the original method.
Example with Jest:
test('Car constructor calls startEngine', () => { // Create a mock function to track calls const mockStartEngine = jest.fn(); // Define a subclass that replaces startEngine with our mock class TestCar extends Car { startEngine = mockStartEngine; } // Instantiate the test class (this triggers the constructor) new TestCar(); // Assert the mock was called exactly once expect(mockStartEngine).toHaveBeenCalledTimes(1); });
Example with Sinon:
const sinon = require('sinon'); describe('Car', () => { it('calls startEngine during instantiation', () => { const mockStartEngine = sinon.spy(); class TestCar extends Car { startEngine = mockStartEngine; } new TestCar(); sinon.assert.calledOnce(mockStartEngine); }); });
Method 2: Override the Class Field Directly
If you don't want to create a subclass, you can temporarily replace the startEngine field on the original Car class with a mock. Just make sure to restore the original method after your test to avoid breaking other tests.
Example with Jest:
test('Car constructor calls startEngine', () => { const mockStartEngine = jest.fn(); // Save the original startEngine to restore later const originalStartEngine = Car.prototype.startEngine; // Override the class field with our mock Object.defineProperty(Car, 'startEngine', { value: mockStartEngine, writable: true }); new Car(); expect(mockStartEngine).toHaveBeenCalledTimes(1); // Restore the original method Object.defineProperty(Car, 'startEngine', { value: originalStartEngine, writable: true }); });
Why This Works
Class field arrow functions are initialized inside the constructor when each instance is created. By replacing this field (either via a subclass or direct override), we ensure the constructor calls our mock instead of the original implementation.
内容的提问来源于stack exchange,提问作者medihack

