使用Sinon Stub模拟Axios请求时遇TypeError:无法读取undefined的then属性
问题排查:Sinon Stub模拟Axios两次POST请求失败
下面是你的代码中存在的几个问题及修正方案:
1. 语法错误:response变量定义错误
测试代码里的response用了TypeScript类型注解写法,但当前是JavaScript环境,语法不合法,需要改成赋值语句:
let response = { data: { url: 'abc' } };
2. 未定义测试依赖变量
测试中的endpoint、id、headers没有提前声明,直接使用会导致ReferenceError,需要在测试块前定义这些变量:
const endpoint = '/test-api'; const id = 'user-123'; const headers = { 'Content-Type': 'application/json' };
3. 第二次Stub返回值不符合函数预期
原函数第二次POST请求的回调里会读取result.data,但你当前Stub返回的是response.data(即{url: 'abc'}),这会导致result.data为undefined,不符合函数逻辑。应该让第二次Stub返回一个包含data属性的完整响应对象:
stubPost.withArgs('abc', id).returns(Promise.resolve({ data: { name: 'test-info' } }));
4. 异步测试未等待Promise完成
getInfo是异步函数,返回Promise,但测试中调用时没加await,会导致测试在Promise执行完成前就结束,进而出现报错或断言失效。必须添加await:
const res = await getInfo(endpoint, headers, id);
5. Sinon Stub的withArgs与onCall混用冲突
同时使用withArgs和onCall时,Sinon的参数匹配逻辑可能出现异常。建议调整Stub的写法,要么按调用次数指定返回值,要么明确匹配参数:
- 按调用次数Stub(无需严格参数匹配):
stubPost .onFirstCall().returns(Promise.resolve(response)) .onSecondCall().returns(Promise.resolve({ data: { name: 'test-info' } }));
- 严格匹配参数的写法:
stubPost.withArgs(endpoint, id).returns(Promise.resolve(response)); stubPost.withArgs('abc', id).returns(Promise.resolve({ data: { name: 'test-info' } }));
修正后的完整测试代码
const axios = require('axios').default; const sinon = require('sinon'); const { getInfo } = require('./index'); describe('To test response', function () { let response; const endpoint = '/test-api'; const id = 'user-123'; const headers = { 'Content-Type': 'application/json' }; // 每次测试前初始化Stub和response beforeEach(function () { response = { data: { url: 'abc' } }; sinon.stub(axios, 'post'); }); // 每次测试后恢复Axios的post方法,避免污染其他测试 afterEach(function () { axios.post.restore(); }); test('success', async function () { axios.post .withArgs(endpoint, id).returns(Promise.resolve(response)) .withArgs('abc', id).returns(Promise.resolve({ data: { name: 'test-info' } })); const res = await getInfo(endpoint, headers, id); // 可以添加断言验证结果是否符合预期 expect(res).toEqual({ name: 'test-info' }); }); });
内容的提问来源于stack exchange,提问作者Min Yoongi
相关产品推荐
相关产品推荐

