You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js TypeScript环境下使用Jest模拟Stripe API遇到的问题

Fixing "Cannot read property 'create' of undefined" When Mocking Stripe with Jest

Let's break down why your current approaches aren't working and fix them step by step. The core issue here is that your stripe.ts module exports a pre-initialized Stripe instance, not the Stripe constructor function. Your mock setups weren't matching this export structure, leading to the undefined error.

Why Your Original Methods Failed

  1. Method 1 (mocks directory): You mocked the Stripe constructor, but your business code imports the already-created instance from stripe.ts, not the constructor itself. Modifying Stripe.prototype had no effect on the instance your code was actually using.
  2. Method 2 (Direct test mock): You returned a function from your mock instead of an object matching the Stripe instance structure. Your code tried to access stripe.customers on a function, which doesn't have that property—hence the undefined error.

Solution 1: Use a mocks Directory Correctly

Since your module exports an instance, your mock should export a matching mock instance.

Step 1: Create the Mock File

Create src/payment-gateways/__mocks__/stripe.ts (note the directory placement: it should sit alongside the real stripe.ts, not in your tests folder):

// src/payment-gateways/__mocks__/stripe.ts
const mockCustomerCreate = jest.fn(() => Promise.resolve({ id: 'test-customer-123' }));

export default {
  customers: {
    create: mockCustomerCreate
  }
};

Step 2: Use the Mock in Your Test

In stripe.test.ts, tell Jest to use your mock and assert against it:

// src/tests/stripe.test.ts
import stripe from '../../payment-gateways/stripe';

// Enable the mock for the stripe module
jest.mock('../../payment-gateways/stripe');

describe('stripe workflow', () => {
  beforeEach(() => {
    // Reset mock calls between tests to avoid cross-test pollution
    jest.clearAllMocks();
  });

  it('creates a customer', async () => {
    // Execute your business logic (e.g., Apollo mutation)
    await apollo.mutate({ /* your mutation details */ });

    // Assert the create method was called
    expect(stripe.customers.create).toHaveBeenCalled();
    // Optional: Assert with specific expected parameters
    expect(stripe.customers.create).toHaveBeenCalledWith({
      email: 'test@example.com',
      // Add other expected fields here
    });
  });
});

Solution 2: Direct Mock in the Test File

If you prefer not to use a mocks directory, adjust your direct mock to return an object matching the Stripe instance structure (not a function):

// src/tests/stripe.test.ts
// Mock the stripe module directly, returning a mock instance
jest.mock('../../payment-gateways/stripe', () => ({
  customers: {
    create: jest.fn(() => Promise.resolve({ id: 'test-customer-123' }))
  }
}));

import stripe from '../../payment-gateways/stripe';

describe('stripe workflow', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('creates a customer', async () => {
    await apollo.mutate({ /* your mutation details */ });

    expect(stripe.customers.create).toHaveBeenCalled();
  });
});

Key Takeaways

  • Always match your mock structure to what your module actually exports. Since stripe.ts exports an instance, your mock must be an object with the same properties (like customers.create).
  • Use jest.clearAllMocks() in beforeEach to reset mock state between tests, ensuring clean test runs.
  • If you need to mock more Stripe methods later, just extend the mock object with additional properties (e.g., charges: { create: jest.fn() }).

内容的提问来源于stack exchange,提问作者PmmZenha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 20:48:12