【问题标题】:express body-parser utf-8 error in test在测试中表达 body-parser utf-8 错误
【发布时间】:2020-12-26 18:50:15
【问题描述】:

对此感到非常困惑。我有一些服务器代码由于某种原因在我的测试中引发 UTF-8 错误,但在正常运行服务器时工作正常:

代码:

export default ({ projectId = PROJECT_ID, esHost = ES_HOST } = {}) => {
  let app = express();
  app.use(cors());
  app.use(bodyParser.json({ limit: '50mb' }));

  let http = Server(app);
  let io = socketIO(http);

  let server = {
    app,
    io,
    http,
    status: 'off',
    listen(
      port = PORT,
      cb = () => {
        rainbow(`⚡️ Listening on port ${port} ⚡️`);
      },
    ) {
      this.http.listen(port, () => {
        main({ io, app, projectId, esHost, port });
        this.status = 'on';
        cb();
      });
    },
    close(cb = () => {}) {
      if (this.http) {
        this.http.close(() => {
          this.status = 'off';
          cb();
        });
      } else {
        throw '❗️ cannot close server that has not been started ❗️';
      }
    },
  };

  return server;
};

用法(完全一样,但开玩笑的测试 body-parser 不能正常工作):

import createServer from '../server'

let server = createServer()
server.listen(5050);

我正在使用邮递员,在测试之外发布回复:

{
    "projects": [
        {
            "id": "test",
            "active": true,
            "timestamp": "2018-02-25T21:33:08.006Z"
        },
        {
            "id": "TEST-PROJECT",
            "active": true,
            "timestamp": "2018-03-05T21:34:34.604Z"
        },
        {
            "id": "asd",
            "active": true,
            "timestamp": "2018-03-06T23:29:55.348Z"
        }
    ],
    "total": 3
}

在 jest 测试服务器中出现意外的 post 响应:

错误

UnsupportedMediaTypeError: 不支持的字符集“UTF-8”
  在 /Users/awilmer/Projects/arranger/node_modules/body-parser/lib/read.js:83:18
  在 invokeCallback (/Users/awilmer /Projects/arranger/node_modules/raw-body/index.js:224:16)
 在 _combinedTickCallback (internal/process/next_tick.js:131:7)
  在 process._tickCallback (internal/process/next_tick .js:180:9)

【问题讨论】:

  • 全部安装完毕,测试全部通过,您是否尝试删除 node_modules、npm cache clean 并重新安装所有内容?
  • 你用哪个操作系统来测试这个?
  • 我正在运行 osx 10.12.6..nodejs 8.4。我将在另一台机器上尝试全新安装
  • @azium,我可以重现你的问题,这个问题只是在这里开玩笑。它不会发生在其他框架中。我现在正在寻找可能的解决方案
  • @azium,发布了解决方案。看看

标签: node.js express postman jestjs body-parser


【解决方案1】:

所以我能够重现问题并找到问题的根源以及解决方法以使其正常工作。该问题是由jest 框架引起的。

在您继续阅读该主题的其余部分之前,我建议您阅读另一个我很早就回答的 Jest 主题。这将有助于获得有关jestrequire 方法的一些上下文内部信息

Specify code to run before any Jest setup happens

原因

该问题仅发生在测试中,而不是在生产中。这是因为jest require 方法。

当您运行测试时,它会启动一个快速服务器,该服务器调用node_modules/raw-body/index.js,如下图所示

如您所见,encodingsnull。这是因为iconv-lite 模块会延迟加载encodings。只有在执行getCodec 方法时才会加载编码。

现在,当您的测试触发 API 时,服务器需要读取正文,以便调用 getCodec

然后通过jest-runtime/build/index.js 自定义require 方法(如果您阅读上一个链接,该方法已重载)。

execModulethis._environment.global 进行了检查,在这种情况下它是空白的,因此会返回 null 值并且模块永远不会被执行

现在当您查看 encodings 模块的导出时,它只是一个空白对象

所以问题纯粹是jest。一个功能玩笑缺乏或主要是一个错误?

相关问题

相关问题已经在下面的帖子中讨论过

https://github.com/facebook/jest/issues/2605

https://github.com/RubenVerborgh/N3.js/issues/120

https://github.com/sidorares/node-mysql2/issues/489#issuecomment-313374683

https://github.com/ashtuchkin/iconv-lite/issues/118

https://github.com/Jason-Rev/vscode-spell-checker/issues/159

修复

解决问题的方法是我们在测试期间加载模块并强制提前加载而不是延迟加载。这可以通过在顶部的index.test.js 中添加一行来完成

import encodings from '../../node_modules/iconv-lite/encodings';
import createServer from '@arranger/server';

更改后所有测试都通过了,虽然测试的 url 有错误所以你得到Cannot POST /

【讨论】:

  • 绝对精彩。我用过的最好的业力。
  • 我一直在尝试为它创建一个小的可重复测试并找出问题所在。但似乎这是你发现的一个边缘案例。即使跨项目延迟加载,express 和 body 解析器也能正常工作。您应该使用 Jest 打开一个问题,并给他们这个 repo 和 SO 链接以重现和解决问题
  • 很好的答案。我刚刚在我的文件顶部添加了require('iconv-lite/encodings');,它神奇地起作用了。
  • 嗨,在导入'../../node_modules/iconv-lite/encodings'之后,在哪里使用分配的变量
  • 你不需要使用它,只需要导入就可以了
【解决方案2】:

我正在添加一个略有不同的解决方案,灵感来自 @Tarun Lalwani

在测试文件的顶部添加以下行。

const encodings = require('./node_modules/iconv-lite/encodings');                                                                                                                                                                       
const iconvLite = require('./node_modules/iconv-lite/lib');                                                                                                                                                                             
iconvLite.getCodec('UTF-8');

【讨论】:

  • 你的 iconvlite 版本是什么?我在 iconvlite 中只看到 utf-7 和 utf-16 版本
【解决方案3】:

我花了很多时间试图弄清楚为什么 Jest 在测试 Node.js 服务器时会报告 415 错误代码。 Node.js 也被配置为在我们的系统上使用app.use(bodyParser.json(...));。这并没有解决问题。

解决方案

使用res.status(...) 时,您必须链接.json() 或也使用res.json()。这意味着如果您以 500 错误或其他方式响应并且您没有返回任何 JSON 数据,您仍然需要使用 res.json()。不知道为什么,因为这首先违背了app.use(bodyParser.json(...)); 的全部目的。

示例

const express = require('express');
const router = express.Router();

router.post("/register", (req, res) => {
  // ...
  res.status(500).json();
  // ...
});

【讨论】:

    猜你喜欢
    • 2013-12-01
    • 2020-03-31
    • 2016-10-31
    • 2015-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-20
    • 2015-05-14
    相关资源
    最近更新 更多