使用 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 中失败

带有 axios 的 firebase 身份验证 rest API 请求

使用 jwt 身份验证保护反应应用程序