Node.js中用Jasmine测试含Promise与EventEmitter的函数返回JSON
我之前也折腾过类似的场景——用Jasmine测Node.js里那种混了Promise和EventEmitter的API请求函数,要验证返回的是原始JSON字符串不是解析后的对象,确实踩了好几个坑。给你分享下我当时解决的思路和步骤:
核心解决思路
首先得搞清楚两个关键点:一是你的函数确实没在内部偷偷解析JSON,二是Jasmine的异步测试要写对,才能精准断言返回值的类型。
1. 先排查函数本身的逻辑
先检查你的函数代码,确保最后返回的是拼接出来的rawData字符串,而不是JSON.parse(rawData)后的对象。比如如果你的函数里有类似下面的错误示例,得把JSON.parse去掉:
// 错误示例:返回了解析后的对象 return new Promise((resolve) => { let rawData = ''; response.on('data', (chunk) => rawData += chunk); response.on('end', () => resolve(JSON.parse(rawData))); // 这里要改成resolve(rawData) });
2. 编写精准的Jasmine测试用例
针对这种异步函数,推荐用async/await来写测试,代码更清晰,也不容易出错。
基础断言写法
如果测试环境允许直接调用真实API,直接断言返回值的类型和内容:
it('should resolve to a raw JSON string, not a JS object', async () => { const apiResponse = await yourApiRequestFunction(); // 第一步:断言类型是字符串 expect(typeof apiResponse).toBe('string'); // 第二步:可选但有用——验证这个字符串是有效的JSON(避免返回格式错误的字符串) expect(() => JSON.parse(apiResponse)).not.toThrow(); // 如果知道预期的JSON结构,可以解析后对比,但重点是原始返回是字符串 const parsedObject = JSON.parse(apiResponse); expect(parsedObject).toEqual({ /* 你的预期对象结构 */ }); });
模拟https请求(更可靠的测试方式)
如果不想依赖真实API,建议模拟https模块的请求响应,完全控制返回的原始数据:
const https = require('https'); const { EventEmitter } = require('events'); beforeEach(() => { // 模拟https.request方法 spyOn(https, 'request').and.callFake((options, responseCallback) => { // 创建模拟的响应对象(EventEmitter) const mockResponse = new EventEmitter(); mockResponse.statusCode = 200; // 异步触发data和end事件,传递预设的JSON字符串 process.nextTick(() => { mockResponse.emit('data', '{"id": 1, "name": "test-item"}'); mockResponse.emit('end'); }); // 返回模拟的request对象,需要有end方法 const mockRequest = new EventEmitter(); mockRequest.end = jasmine.createSpy('end'); responseCallback(mockResponse); return mockRequest; }); }); it('returns the exact raw JSON string from the API', async () => { const result = await yourApiRequestFunction(); expect(typeof result).toBe('string'); // 精准匹配预设的JSON字符串 expect(result).toBe('{"id": 1, "name": "test-item"}'); });
3. 避开常见的测试坑点
- 异步测试没处理好:如果不用
async/await,一定要用done回调,否则Jasmine会提前结束测试,导致断言失效:
it('should return JSON string', (done) => { yourApiRequestFunction() .then(result => { expect(typeof result).toBe('string'); done(); }) .catch(err => done.fail(err)); });
- 忽略了EventEmitter的异步性:确保你的函数是在
end事件触发后才resolve Promise,不要提前resolve,否则可能返回不完整的字符串。
内容的提问来源于stack exchange,提问作者Mr.C
相关产品推荐
相关产品推荐

