Jest单元测试:如何测试if/else分支并按条件真假调用对应方法
前置修正
你贴的源码存在两处会阻断测试的问题,先修正再谈测试:
- 语法错误:函数定义
const valueCheck() = () =>不符合JS语法,正确写法为const valueCheck = () => {} - 逻辑错误:
typeof (props.user.value != undefined)是对括号内的布尔判断结果做类型检测,返回值永远是'boolean',会导致if条件恒成立,完全不符合预期,正确的存在性判断应为typeof props.user.value !== 'undefined'
为了方便测试,建议把方法依赖的props、callResult、notification作为参数传入,避免全局闭包依赖难以mock,修正后的可测试版本如下:
const valueCheck = ({ props, callResult, notification }) => { if (typeof props.user.value !== 'undefined' && props.user.value) { callResult([]); } else { notification.warn(['Wrong value']); } };
测试用例设计逻辑
Jest单元测试的核心是覆盖所有逻辑分支,所有外部依赖全部用mock函数替代,只验证当前方法的输出/调用行为是否符合预期,不需要关心依赖的内部实现。
针对这个方法,一共需要覆盖3类场景:
- 场景1:
props.user.value为已定义的真值(比如非空字符串、非0数字、对象等),验证方法会调用callResult并传入空数组,不会触发警告 - 场景2:
props.user.value为undefined,验证方法会触发警告,不会调用callResult - 场景3:
props.user.value为已定义的假值(比如null、0、空字符串、false、NaN),验证方法会触发警告,不会调用callResult
具体测试代码实现
// 从你的业务文件中引入待测试的valueCheck方法 // import { valueCheck } from './your-business-file-path'; describe('valueCheck 方法测试', () => { // 每个用例执行前重新初始化mock,避免用例之间的调用状态互相污染 let mockProps; let mockCallResult; let mockNotification; beforeEach(() => { mockCallResult = jest.fn(); mockNotification = { warn: jest.fn() }; }); test('入参为已定义真值时,应调用callResult传入空数组,不触发警告', () => { mockProps = { user: { value: 'valid_test_value' } }; valueCheck({ props: mockProps, callResult: mockCallResult, notification: mockNotification }); // 断言验证 expect(mockCallResult).toHaveBeenCalledTimes(1); expect(mockCallResult).toHaveBeenCalledWith([]); expect(mockNotification.warn).not.toHaveBeenCalled(); }); test('入参为undefined时,应触发格式警告,不调用callResult', () => { mockProps = { user: { value: undefined } }; valueCheck({ props: mockProps, callResult: mockCallResult, notification: mockNotification }); expect(mockNotification.warn).toHaveBeenCalledTimes(1); expect(mockNotification.warn).toHaveBeenCalledWith(['Wrong value']); expect(mockCallResult).not.toHaveBeenCalled(); }); test('入参为已定义假值时,应触发格式警告,不调用callResult', () => { const falsyTestValues = [null, 0, '', false, NaN]; falsyTestValues.forEach(testVal => { // 每个值测试前清空mock调用记录 jest.clearAllMocks(); mockProps = { user: { value: testVal } }; valueCheck({ props: mockProps, callResult: mockCallResult, notification: mockNotification }); expect(mockNotification.warn).toHaveBeenCalledWith(['Wrong value']); expect(mockCallResult).not.toHaveBeenCalled(); }); }); });
补充说明
如果你的原方法里的三个依赖是React组件内的闭包变量/全局模块变量,不想改成传参形式,也可以直接用Jest的jest.mock()能力mock对应的依赖模块,测试的断言逻辑和上面的代码完全一致。
注意所有单测用例必须保持独立,不要共享mock的调用状态,否则会出现用例单独跑能过、批量跑失败的问题。
内容的提问来源于stack exchange,提问作者user1881845
相关产品推荐
相关产品推荐

