MSW无法捕获Stripe请求问题排查求助
问题:MSW无法捕获Stripe Node.js库的请求,返回真实数据
我尝试在集成测试中使用MSW模拟对Stripe的服务端调用,测试代码如下:
// @vitest-environment node import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { describe, expect, test } from 'vitest'; import { mockStripePrices, mockStripeProducts, } from '~/test/mocks/fixtures/stripe'; import { fetchProductsWithPrices } from './billing-helpers.server'; const server = setupServer( rest.get('https://api.stripe.com/v1/products', (request, response, context) => response(context.json(mockStripeProducts)), ), rest.get('https://api.stripe.com/v1/prices', (request, response, context) => response(context.json(mockStripePrices)), ), ); beforeAll(() => server.listen({ onUnhandledRequest: 'warn' })); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); describe('fetchProductsWithPrices()', () => { test('given nothing: returns all our products and their prices', async () => { const actual = await fetchProductsWithPrices(); const expected = []; expect(actual).toEqual(expected); }); });
业务代码fetchProductsWithPrices实现如下:
import { stripeAdmin } from './stripe-admin.server'; export async function fetchProductsWithPrices() { const [products, prices] = await Promise.all([ stripeAdmin.products.list({ active: true }), stripeAdmin.prices.list({ active: true }), ]); return products.data.map(product => ({ ...product, prices: prices.data.filter(price => price.product === product.id), })); }
但实际返回的是真实数据而非模拟数据,MSW并未捕获请求。我原以为Node.js Stripe库是REST API的封装,还尝试了GraphQL模拟:
const stripe = graphql.link('https://api.stripe.com/v1/');
但同样无效,请问问题出在哪里?
解答
核心原因
Stripe Node.js SDK默认使用自定义的HTTP请求层(并非Node.js原生的http/https模块),而MSW在Node环境下是通过拦截原生http/https模块或fetch API的请求来工作的,因此默认情况下无法捕获Stripe SDK发出的请求。你尝试的GraphQL模拟方向错误,因为Stripe API是REST架构,并非GraphQL。
解决办法:配置Stripe SDK使用MSW可拦截的HTTP客户端
要让MSW能捕获请求,需要强制Stripe SDK使用fetch API作为请求客户端(MSW支持拦截Node环境下的fetch调用)。具体步骤如下:
- 修改Stripe实例的配置(
stripe-admin.server.ts):
import Stripe from 'stripe'; // Node.js版本低于18时需安装node-fetch并引入,18+可直接用原生fetch import fetch from 'node-fetch'; export const stripeAdmin = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: '2024-06-20', // 替换为你的Stripe API版本 // 仅在测试环境下切换到基于fetch的HTTP客户端 ...(process.env.NODE_ENV === 'test' ? { httpClient: Stripe.createFetchHttpClient({ fetch }) } : {}) });
- 验证MSW拦截逻辑
你的现有MSW REST请求配置是正确的,无需修改。当Stripe SDK使用fetch发送请求后,MSW就能正常捕获并返回模拟数据。
为什么这样有效?
Stripe SDK提供了createFetchHttpClient方法,允许开发者基于标准fetch API构建自定义客户端。MSW在Node环境中会通过猴子补丁拦截fetch调用,因此只要Stripe SDK使用fetch发送请求,就能被MSW正确拦截并返回你定义的模拟响应。
内容的提问来源于stack exchange,提问作者J. Hesters
相关产品推荐
相关产品推荐

