通过Karma测试套件访问UI5自定义中间件时无法解析JSON体问题求助
问题根因分析
1. res扩展方法不生效
@ui5/karma-ui5插件会将UI5自定义中间件挂载到Karma底层的Connect服务栈上,而非直接启动独立的Express服务。res.status()、res.header()都是Express框架对原生HTTP响应对象的扩展方法,Connect服务本身不会注入这些扩展,因此调用不生效。
直接通过ui5 serve启动时,UI5 CLI底层基于Express启动服务,你的自定义Express实例可以正常继承框架注入的扩展方法,因此无异常。
2. JSON解析中间件偶发无响应
有两个核心触发原因:
- 请求体被前置中间件提前消费:Karma自身的内置中间件会优先处理所有入站请求,部分场景下会提前读取请求体的数据流,等请求流转到你的Express JSON解析中间件时,req的可读流已经被消费完毕,中间件会持续等待
end事件触发,最终超时。 - 连接复用冲突:Karma在
singleRun: true模式下,会通过WebSocket和浏览器保持测试状态同步,每完成一部分测试用例就会主动清理闲置的TCP连接。你发起的POST请求如果刚好复用了即将被Karma回收的连接,就会出现Stalled状态。
可行解决思路
修复res扩展方法失效问题
在自定义中间件开头手动注入Express的响应扩展,不依赖外层服务的注入:
const express = require('express'); const { response: expressRes } = express; module.exports = function ({resources, middlewareUtil, options}) { const app = express(); // 手动注入express的res扩展方法 app.use((req, res, next) => { Object.assign(res, expressRes); next(); }); // 后续业务逻辑 }
修复JSON解析偶发卡住问题
- 替换express.json()为原生请求体解析逻辑,避免流重复消费冲突:
app.use((req, res, next) => { if (req.headers['content-type']?.includes('application/json')) { let bodyChunks = []; const reqTimeout = setTimeout(() => { res.statusCode = 408; res.end('request timeout'); }, 10000); // 10s兜底超时 req.on('data', chunk => bodyChunks.push(chunk)); req.on('end', () => { clearTimeout(reqTimeout); try { req.body = JSON.parse(Buffer.concat(bodyChunks).toString()); next(); } catch (e) { res.statusCode = 400; res.end('invalid json payload'); } }); req.on('error', () => { clearTimeout(reqTimeout); res.end(); }); } else { next(); } });
- 调整Chrome启动参数,禁用连接复用:
修改karma.conf.js的自定义启动器配置:
customLaunchers: { Chrome_without_security: { base: 'Chrome', flags: [ '--disable-web-security', '--no-sandbox', '--disable-http-keep-alive', '--disable-connection-pooling' ] } }
- 调整Karma连接容忍配置:
在karma.conf.js中新增以下参数,提高浏览器连接断开的容忍阈值:
browserDisconnectTolerance: 10, browserDisconnectTimeout: 60000
- 调整中间件挂载顺序:
在ui5-testing.yaml中将proxy中间件的beforeMiddleware改为csp,尽量靠前挂载,减少前面中间件消费请求流的概率。
内容的提问来源于stack exchange,提问作者Benjamin Funder
相关产品推荐
相关产品推荐

