使用Jest运行单元测试时遇TypeError错误,求解决方法
问题分析与解决:Mock AWS SDK调用时的reduce未定义错误
我给getOnDemandEnvironmentInstances函数写了Jest单元测试,本来只想验证mockClient的send方法是否被调用,但运行测试时抛出TypeError: Cannot read properties of undefined (reading 'reduce')错误,报错行是被测试函数里对Reservations调用reduce的代码。
单元测试代码
import { jest } from '@jest/globals'; import { getOnDemandEnvironmentInstances } from './../getOnDemandEnvironmentInstances'; import { MockClient } from './aws-sdk-client-mock'; describe('getOnDemandEnvironmentInstances', () => { it('should return instances correctly when there are reservations and instances', async () => { const mockClient = new MockClient; const mockClientSend = jest.spyOn(mockClient, "send"); await getOnDemandEnvironmentInstances(mockClient); expect(mockClientSend).toHaveBeenCalled(); }); });
错误信息
13 | const Reservations = data.Reservations; 14 | > 15 | const instanceList = Reservations.reduce((prev, current) => { | ^ 16 | return prev.concat(current.Instances); 17 | }, []);
被测试函数代码
import { DescribeInstancesCommand } from "@aws-sdk/client-ec2"; export async function getOnDemandEnvironmentInstances(ec2Client) { const describeInstancesCommand = new DescribeInstancesCommand({ Filters: [ { Name: "tag:Phase", Values: ["OnDemandEnv"] }, { Name: "tag:CbzStackTag", Values: ["cbzwebtier-test-ondemand"] }, { Name: "tag:Platform", Values: ["Windows"] }, ], }); const data = await ec2Client.send(describeInstancesCommand); const Reservations = data.Reservations; const instanceList = Reservations.reduce((prev, current) => { return prev.concat(current.Instances); }, []); return instanceList; }
问题原因
你的mockClient没有模拟send方法的返回值,导致调用ec2Client.send后返回的data对象里没有Reservations属性,Reservations变成undefined,调用reduce自然会报错。哪怕你只关心send是否被调用,测试运行时被测试函数还是会执行完整逻辑,必须保证mock返回符合预期的结构,避免代码执行到报错分支。
修改方案
1. 修正单元测试代码
让mock的send方法返回包含Reservations的模拟数据,同时保留对send调用的验证:
import { jest } from '@jest/globals'; import { getOnDemandEnvironmentInstances } from './../getOnDemandEnvironmentInstances'; import { MockClient } from './aws-sdk-client-mock'; import { DescribeInstancesCommand } from "@aws-sdk/client-ec2"; describe('getOnDemandEnvironmentInstances', () => { it('should return instances correctly when there are reservations and instances', async () => { const mockClient = new MockClient; // 模拟send方法返回符合结构的AWS响应数据 jest.spyOn(mockClient, "send").mockResolvedValue({ Reservations: [ { Instances: [{ InstanceId: 'i-12345' }] }, { Instances: [{ InstanceId: 'i-67890' }] } ] }); await getOnDemandEnvironmentInstances(mockClient); // 验证send被调用,且参数是正确的DescribeInstancesCommand实例 expect(mockClient.send).toHaveBeenCalledWith(expect.any(DescribeInstancesCommand)); }); });
2. 优化被测试函数(可选但推荐)
为了避免生产环境中因为AWS返回数据异常导致报错,给Reservations和Instances设置默认值:
import { DescribeInstancesCommand } from "@aws-sdk/client-ec2"; export async function getOnDemandEnvironmentInstances(ec2Client) { const describeInstancesCommand = new DescribeInstancesCommand({ Filters: [ { Name: "tag:Phase", Values: ["OnDemandEnv"] }, { Name: "tag:CbzStackTag", Values: ["cbzwebtier-test-ondemand"] }, { Name: "tag:Platform", Values: ["Windows"] }, ], }); const data = await ec2Client.send(describeInstancesCommand); // 给Reservations设置默认空数组,避免undefined调用reduce const Reservations = data.Reservations || []; const instanceList = Reservations.reduce((prev, current) => { // 给Instances也加默认值,防止单条Reservation没有Instances的情况 return prev.concat(current.Instances || []); }, []); return instanceList; }
内容的提问来源于stack exchange,提问作者Madhuri Verma
相关产品推荐
相关产品推荐

