You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Jest测试分组函数返回的正确对象?(返回[Function Anonymous]问题)

Jest验证分组函数失败的解决方法及最佳实践

问题背景

我用Lodash实现了一个分组函数,逻辑是过滤指定属性不为null的对象,再按该属性分组:

const sort = 
  (pets, attribute) =>
    _(pets)
      .filter(pet => _.get(pet, attribute) !== null)
      .groupBy(attribute)
      .value()

测试数据如下:

const pets= [{
    id: 1,
    name: 'snowy',
  },
  {
    id: 2,
    name: 'quacky',
  },
  {
    id: 3,
    name: 'snowy',
    age: 5,
  },
  {
    id: null,
    name: null,
    age: null
  }
]

const attribute = 'name'

执行sort(pets, attribute)后预期返回:

{
  snowy: [ { id: 1, name: 'snowy' }, { id: 3, name: 'snowy', age: 5} ],
  quacky: [ { id: 2, name: 'quacky' } ]
}

但我写的Jest测试代码执行失败:

const res = sort(users,key)
expect(res).toEqual(
  expect.arrayContaining([
    expect.objectContaining({'snowy' : [ { id: 1, name: 'snowy' }, { id: 3, name: 'snowy', age: 5 } ]},
    expect.objectContaining({'quacky' : [ { id: 2, name: 'quacky' } ]}))
  ])
)

错误信息显示:

Expected: ArrayContaining [ObjectContaining {"snowy": [{"id": 1, "name": "snowy"}, {"age": 5, "id": 3, "name": "snowy"}]}]
Received: [Function anonymous]

错误原因分析

  1. 变量名错误:测试代码中使用了未定义的users和key,而非正确的pets和attribute,导致函数执行异常。
  2. 断言类型不匹配:分组函数返回的是对象,但测试中误用了expect.arrayContaining(用于断言数组),完全不符合返回值类型。
  3. 断言结构错误:expect.objectContaining的嵌套逻辑错误,不需要将对象包裹在数组断言中。

正确的Jest测试代码

针对分组函数的返回值类型,有两种常用的断言方式:

方式1:直接断言完整对象结构

适合返回结果明确、结构固定的场景:

test('按name属性正确分组并过滤null值', () => {
  const pets = [{
    id: 1,
    name: 'snowy',
  },
  {
    id: 2,
    name: 'quacky',
  },
  {
    id: 3,
    name: 'snowy',
    age: 5,
  },
  {
    id: null,
    name: null,
    age: null
  }];
  const attribute = 'name';
  const result = sort(pets, attribute);

  expect(result).toEqual({
    snowy: [
      { id: 1, name: 'snowy' },
      { id: 3, name: 'snowy', age: 5 }
    ],
    quacky: [ { id: 2, name: 'quacky' } ]
  });
});

方式2:部分匹配断言

适合只需要验证关键属性,忽略其他细节的场景:

test('分组结果包含指定键及对应内容', () => {
  const pets = [/* 测试数据同上 */];
  const attribute = 'name';
  const result = sort(pets, attribute);

  // 验证snowy分组的内容
  expect(result).toHaveProperty('snowy', expect.arrayContaining([
    expect.objectContaining({ id: 1, name: 'snowy' }),
    expect.objectContaining({ id: 3, name: 'snowy' })
  ]));
  // 验证quacky分组的内容
  expect(result).toHaveProperty('quacky', expect.arrayContaining([
    expect.objectContaining({ id: 2, name: 'quacky' })
  ]));
  // 验证name为null的项被过滤
  expect(result).not.toHaveProperty(null);
});

分组函数的最佳测试方法

为了确保函数的鲁棒性,需要覆盖多种场景:

  • 正常分组场景:验证多个相同属性值的对象被正确归为一组
  • 过滤逻辑验证:确认属性值为null的对象被排除
  • 边界场景测试:
    • 传入空数组,返回空对象
    • 传入不存在的属性,验证分组行为(当前函数会将属性不存在的项分到undefined键下)
    • 传入属性值为undefined的对象,验证是否被保留(当前函数逻辑中undefined !== null,所以会被保留)
  • 单一对象场景:传入单个有效对象,返回对应键的数组

示例测试用例:

test('传入空数组返回空对象', () => {
  expect(sort([], 'name')).toEqual({});
});

test('传入不存在的属性,将所有项分组到undefined键下', () => {
  const pets = [{ id: 1 }, { id: 2 }];
  expect(sort(pets, 'nonexistent')).toEqual({
    undefined: [ { id: 1 }, { id: 2 } ]
  });
});

test('属性值为undefined的项会被保留并分组', () => {
  const pets = [{ id: 1, name: undefined }, { id: 2 }];
  expect(sort(pets, 'name')).toEqual({
    undefined: [ { id: 1, name: undefined }, { id: 2 } ]
  });
});

内容的提问来源于stack exchange,提问作者Daichi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 06:18:20