跨域错误 - 错误:仅在ReactJS / Jest测试中跨域访问http://localhost被禁止。

15
我遇到了一个问题,我向外部API发送的请求在执行时效果很好,但是在运行Jest/Enzyme测试时会出现CORS错误。涉及的函数使用API中的JsonRpc实现,并使用node-fetch进行提取。不确定是否可以在某个地方应用CORS设置?我在Jest/Enzyme测试框架中尝试了许多异步等待的变体,但仍然存在问题。
test("it should do something", done => {
    const component = shallow(<CustomComponent />)
    component.instance().customAsyncFunction( result => {
      expect(result.length).toEqual(5)
      done()
    })
    // return component.instance().customAsyncFunction().then(data => {
    //   expect(data.length).toEqual(5)
    // })
  })

我尝试了上述方法和其他几种方法(如 setTimeout 和等待它),但都遇到了 CORS 错误。

我得到的结果是:

 console.error
 node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/virtual-console.js:29
   Error: Cross origin http://localhost forbidden
       at dispatchError (...\node_modules\jest-environment-jsdom\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:65:19)
       at Request.client.on.res (...\node_modules\jest-environment-jsdom\node_modules\jsdom\lib\jsdom\living\xmlhttprequest.js:679:38)
       at Request.emit (events.js:198:13)
       at Request.onRequestResponse (...\node_modules\request\request.js:1066:10)
       at ClientRequest.emit (events.js:203:15)
       at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:556:21)
       at HTTPParser.parserOnHeadersComplete (_http_common.js:109:17)
       at TLSSocket.socketOnData (_http_client.js:442:20) undefined

有什么想法吗?


1
你在浏览器中运行测试吗?因为CORS检查通常是针对浏览器的,但我认为对于NodeJS来说这并不是预期的。 - skyboyer
6个回答

6

出现此错误是因为在测试期间调用的外部 API 具有与 Jest 的默认 jsdom 不同的 CORS 限制(http://localhost)。

要在 Jest v24 - v27 中修复此问题,您必须在 Jest 配置文件(例如 jest.config.js)中设置适当的 testURL(请参见文档):

{
    // Other config values here ...
    "testURL": "http://localhost:8080"
}

testURL中,您必须放置远程API端允许的实际URL,以便CORS能够使用。

NB:自v28以来,该选项的组织方式已经不同,需要在Jest配置中进行不同的更新。


6
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;

我实际上正在使用XMLHttpRequest。除此之外,我还能做什么? - AEB
2
我仍然需要全局的XMLHttpRequest工作,所以我使用了一个npm包xhr2,然后使用global.XMLHttpRequest = require('xhr2');进行替换。 - Richard Tyler Miles
1
@RichardTylerMiles 非常感谢,我成功解决了CORS错误。 - Chandler Bing

3

假设您希望在测试过程中实际调用真正的API而不仅仅是模拟它,那么您需要确保服务器发送适当的“access-control-allow-origin”标头(显然,如何实现取决于您的服务器平台)。


1

1) 你可能想要使用jest.mock()来模拟Promise或其他正在运行的函数,然后断言该模拟被调用(使用正确的参数)。Jest测试是单元测试,不应该与API交互。

2) 在测试模式下,很可能是由于环境变量的问题。在Jest期间,process.env.NODE_ENV设置为“test”,这可能会改变某些内容,或者可能是您自己的自定义配置环境变量之一。


1

0

我建议使用supertest库:

yarn add -D supertest / npm install supertest --save-dev

并在你的测试脚本中调用request

import request from "supertest";

try {
    const response = await request('http://...')
        .post('api/v1/...')
        .send(payload);
    return response.body;
}
catch(err) {
    ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接