Jest测试Mock Twilio短信创建函数报错:Cannot set properties of undefined
解决Twilio API测试中无法Mock短信创建函数的问题
错误原因
你遇到的TypeError: Cannot set properties of undefined (setting 'create'),核心问题是直接操作twilio模块本身的messages属性,但该属性并不存在。业务代码里实际是通过twilio(twilioAccountSid, twilioAuthToken)生成客户端实例client,再调用client.messages.create;而测试中你mock的是twilio模块的messages,和业务代码里的客户端实例完全不是同一个对象,自然会报错。
解决方案
1. 正确Mock Twilio客户端
使用Jest的jest.mock来mock整个twilio模块,让它返回一个模拟的构造函数,这样业务代码中生成的client就是可控的mock对象。修改server.test.js如下:
require('@babel/register')({ presets: ['@babel/preset-env'] }); require('dotenv').config(); // 加载环境变量,确保测试中能获取TWILIO_PHONE_NUMBER import request from 'supertest'; import app from './server.mjs'; import twilio from 'twilio'; // Mock Twilio模块,返回模拟的客户端构造函数 jest.mock('twilio', () => { const mockMessagesCreate = jest.fn().mockResolvedValue({ sid: 'some-message-sid' }); const mockClient = { messages: { create: mockMessagesCreate } }; return jest.fn(() => mockClient); }); // 获取mock的客户端实例和create方法 const mockClient = twilio(); const mockCreate = mockClient.messages.create; describe('Server endpoints', () => { it('should send a verification code via SMS (mocked)', async () => { mockCreate.mockClear(); // 重置mock调用记录,避免跨测试污染 const response = await request(app) .post('/send-verification-code') .send({ formattedPhoneNumber: '+447720761143' }); expect(response.status).toBe(200); expect(response.body).toHaveProperty('verificationCode'); expect(mockCreate).toHaveBeenCalledWith({ body: expect.stringContaining('verification code'), from: process.env.TWILIO_PHONE_NUMBER, to: '+447720761143', }); }); });
2. 优化业务代码(可选但推荐)
原server.mjs中存在await和.then/.catch混用的问题,导致错误处理逻辑冗余,建议统一使用try/catch:
// 替换原send-verification-code端点代码 app.post('/send-verification-code', async (req, res) => { console.log('Endpoint reached: /send-verification-code'); const { formattedPhoneNumber } = req.body; console.log('Received request with formattedPhoneNumber:', formattedPhoneNumber); try { const verificationCode = Math.floor(100000 + Math.random() * 900000); const message = await client.messages.create({ body: `G-${verificationCode} is your Google verification code.`, from: twilioPhoneNumber, to: formattedPhoneNumber, }); console.log('Twilio API call successful:', message.sid); console.log('Verification code:', verificationCode); res.json({ sid: message.sid, verificationCode: verificationCode, }); } catch (error) { console.error('Twilio API call error:', error.response ? error.response.data : error); res.status(500).json({ error: 'Internal Server Error' }); } });
内容的提问来源于stack exchange,提问作者Jake Matthews
相关产品推荐
相关产品推荐

