使用 axios 执行经过身份验证的请求时,Jest 返回“网络错误”
Posted
技术标签:
【中文标题】使用 axios 执行经过身份验证的请求时,Jest 返回“网络错误”【英文标题】:Jest returns "Network Error" when doing an authenticated request with axios 【发布时间】:2017-07-29 09:04:42 【问题描述】:这对我来说似乎有点奇怪。我正在尝试使用 Jest 测试实际(即真实网络)请求。
这些是经过测试的场景:
测试没有标头的外部 API (fixer.io) 使用标头测试本地 API 服务器 使用来自node
终端的标头测试相同的本地 API
这种行为背后的原因可能是什么?解决办法是什么?
//This WORKS
test('testing no headers', () =>
return axios.get('http://api.fixer.io/latest')
.then( res => console.log(res) )
);
//This DOES NOT work
test('testing no headers', () =>
return axios.get('http://localhost:3000/users/4/profile',
headers:authorization:`Bearer $mytoken`)
.then( res => console.log(res) )
);
//...
//Node Terminal
//This WORKS
> axios.get('http://localhost:3000/users/4/profile',
headers:authorization:`Bearer $mytoken`)
.then( res => console.log(res) )
【问题讨论】:
【参考方案1】:这可能是 Jest 配置问题。我解决了在 package.json 中强制“节点”作为开玩笑环境:
“笑话”: “测试环境”:“节点”
参见文档:https://facebook.github.io/jest/docs/configuration.html#testenvironment-string
【讨论】:
这有助于我提出获取请求。但是我仍然收到发布请求的错误。有什么线索吗? 很好的解决方案! @sbkl 在将节点环境用于 POST 和 PUT 时得到 [参考错误:未定义提取]。 Node 环境无法像 jsdom 那样访问 window.fetch,因此您必须使用对浏览器和服务器都友好的 fetch 库,例如 one 如果你打了很多电话,你可能还想延长超时时间...... jest.setTimeout(600000)【参考方案2】:搞笑的是,axios通过primary使用XMLHttpRequest,ajax请求不能跨域访问,所以你的测试失败了,所以你可以通过设置axios适配器让你的代码通过。
axios/defaults.js 的原因
function getDefaultAdapter()
var adapter;
if (typeof XMLHttpRequest !== 'undefined')
// For browsers use XHR adapter
adapter = require('./adapters/xhr');
else if (typeof process !== 'undefined')
// For node use HTTP adapter
adapter = require('./adapters/http');
return adapter;
解决方法将axios适配器改为http
import axios from 'axios';
//This WORKS
test('testing with headers', (done) =>
var path=require('path');
var lib=path.join(path.dirname(require.resolve('axios')),'lib/adapters/http');
var http=require(lib);
axios.get('http://192.168.1.253',
adapter: http,
headers:
Authorization: "Basic YWRtaW46bHVveGlueGlhbjkx"
).then((res) =>
expect(res.status).toBe(200);
done();
).catch(done.fail);
);
解决方案更改 package.json 中的 jest testURL
"jest":
"testURL":"http://192.168.1.253"
那么测试就可以通过ajax访问http了
import axios from 'axios';
//This WORKS
test('testing with headers', (done) =>
axios.get('http://192.168.1.253',
headers:
Authorization: "Basic YWRtaW46bHVveGlueGlhbjkx"
).then((res) =>
expect(res.status).toBe(200);
done();
).catch(done.fail);
);
【讨论】:
感谢您的回复。我怀疑它与适配器有关。我现在对 package.json 中的testURL
参数感到很困惑。我确实有一个我忘记的旧设置 localhost:8080
,现在更改为 localhost:3000
确实 使它工作。我会试着弄清楚Jest
是如何使用这个有冲突的testURL
参数...
问题是ajax跨域访问,因为jsdom默认url在jest是about:blank
,我试过改document.url
但不成功,只有通过testURL
选项可以改ajax origin
网址。
但是 Jest 不应该注意是否有东西(即本例中的 axios)指定了另一个域吗?如果不同的测试向同一个应用中的不同域发出请求怎么办?
我没有找到解决这个问题的办法,只能换axios adapers。
@Arseniy-II 不幸的是,我来自中国,在 SO 上看不到您的问题的图像。我在这里的回答假设 OP 在运行测试之前已经启动了本地资源服务器在端口 3000
上侦听,因此您应该确保自己的资源服务器首先启动。【参考方案3】:
Jest 允许您设置设置脚本文件。该文件在其他所有内容之前都是必需的,它使您有机会修改运行测试的环境。这样,您可以在加载 axios 之前取消设置 XMLHttpRequest,并在提升导入后评估适配器类型。 https://facebook.github.io/jest/docs/configuration.html#setuptestframeworkscriptfile-string
这对我有用:
package.json
...,
"jest":
...,
"setupTestFrameworkScriptFile": "./__tests__/setup.js",
...
,
...
__tests__/setup.js
global.XMLHttpRequest = undefined;
【讨论】:
不错的解决方案,但需要将setup.js
移出__tests__
文件夹,否则您将收到setup.js
文件中测试失败的错误【参考方案4】:
我通过添加解决了它
axios.defaults.adapter = require('axios/lib/adapters/http');
对于特定的测试用例文件,因为设置 global.XMLHttpRequest = undefined 或 env=node 导致我的其他测试用例失败。
【讨论】:
以上是关于使用 axios 执行经过身份验证的请求时,Jest 返回“网络错误”的主要内容,如果未能解决你的问题,请参考以下文章
使用浏览器中现有的经过身份验证的会话在python上执行https请求
我们如何在 Linux 上使用 axios 发送带有 Kerberos 身份验证的 post 请求?
POST 请求的身份验证错误:“未提供身份验证凭据”使用 Axios,但使用 POSTMAN 工作
使用身份验证令牌的 Axios 请求有时会在 Safari 中失败