使用MSW(mock service worker)模拟流响应时未设置响应体的问题
解决MSW测试流响应时
response.body为undefined的问题 你的问题出在MSW默认不会将ctx.body()传入的ArrayBuffer自动包装成ReadableStream,而fetch响应的body属性要求是ReadableStream类型,直接传ArrayBuffer会导致response.body返回undefined。
修复方案
- 在MSW响应中手动创建
ReadableStream实例并传入ctx.body() - 调整测试断言逻辑:由于
ReadableStream实例无法直接做严格相等对比,需要读取流内容后验证数据正确性
修改后的代码示例
请求方法(无需改动)
const apiRequest = async (route) => { const response = await fetch(route, { cache: 'no-cache', method: 'post', }); return { stream: response.body }; };
测试代码
import { rest } from 'msw'; import { setupServer } from 'msw/node'; const server = setupServer([]); // 辅助工具:读取ReadableStream的内容 const readStreamContent = async (stream) => { const reader = stream.getReader(); const chunks = []; let readResult; while (!(readResult = await reader.read()).done) { chunks.push(readResult.value); } return new Uint8Array(Buffer.concat(chunks)); }; it('returns stream in the response', async () => { const url = '/mockUrl'; const encoder = new TextEncoder(); const testContent = encoder.encode('this is mocking a stream'); server.use(rest.post(url, (req, res, ctx) => { // 创建符合要求的ReadableStream const mockStream = new ReadableStream({ start(controller) { controller.enqueue(testContent); controller.close(); }, }); return res( ctx.status(200), ctx.set('Content-Length', testContent.byteLength.toString()), ctx.set('Content-Type', 'application/octet-stream'), ctx.body(mockStream), ); })); const response = await apiRequest(url); const streamContent = await readStreamContent(response.stream); // 验证流内容与测试数据一致 expect(streamContent).toEqual(testContent); });
关键细节说明
- MSW支持直接传入
ReadableStream作为响应体,这样fetch返回的response.body会是有效的流对象 - 不要尝试直接对比
ReadableStream实例:每个流实例都是唯一的,必须读取内容后验证数据本身 - 合理设置
Content-Type:推荐使用application/octet-stream作为二进制流的类型,避免不必要的解析干扰
内容的提问来源于stack exchange,提问作者Marcus Ruddick
相关产品推荐
相关产品推荐

