在Jest中测试基于状态的filterProducts函数的方法咨询
filterProducts 函数的完整方案 Alright, let's break down how to thoroughly test your filterProducts function. Since it’s tied to your component’s state, we need to cover all logical scenarios and edge cases to ensure it behaves as expected. Here’s a step-by-step approach:
先理清楚测试的核心逻辑
Your function does two key things:
- Iterates over each product in
this.state.products - Checks if any of the product’s categories have a
titlematchingthis.state.chosenCategory - Returns only the products that pass this check
So our tests need to validate every possible outcome of this logic.
具体测试用例 & 实现方式
1. 正常场景:单个产品匹配选中类别
This is the "happy path"—make sure the function correctly picks out a product that belongs to the chosen category.
// 模拟组件实例和状态 const component = new YourComponent(); component.state = { chosenCategory: "Electronics", products: [ { id: 1, categories: [{ title: "Electronics" }, { title: "Gadgets" }] }, { id: 2, categories: [{ title: "Books" }] } ] }; const filtered = component.filterProducts(); // 断言只返回匹配的产品 expect(filtered).toEqual([{ id: 1, categories: [{ title: "Electronics" }, { title: "Gadgets" }] }]); // 也可以断言长度,不过具体对象匹配更严谨 expect(filtered.length).toBe(1);
2. 无匹配场景:没有产品属于选中类别
Test that the function returns an empty array when no products match the chosen category.
component.state = { chosenCategory: "Furniture", products: [ { id: 1, categories: [{ title: "Electronics" }] }, { id: 2, categories: [{ title: "Books" }] } ] }; const filtered = component.filterProducts(); expect(filtered).toEqual([]);
3. 多匹配场景:多个产品符合选中类别
Verify that all qualifying products are included in the result.
component.state = { chosenCategory: "Clothing", products: [ { id: 1, categories: [{ title: "Clothing" }, { title: "Shoes" }] }, { id: 2, categories: [{ title: "Clothing" }] }, { id: 3, categories: [{ title: "Books" }] } ] }; const filtered = component.filterProducts(); expect(filtered.length).toBe(2); // 断言具体的产品ID存在,避免对象引用问题 expect(filtered.map(p => p.id)).toEqual([1, 2]);
4. 边界场景:空产品数组
Ensure the function handles an empty products array gracefully (no errors, returns empty array).
component.state = { chosenCategory: "Electronics", products: [] }; const filtered = component.filterProducts(); expect(filtered).toEqual([]);
5. 边界场景:产品的categories数组为空
A product with no categories should never be included, regardless of the chosen category.
component.state = { chosenCategory: "Electronics", products: [ { id: 1, categories: [] }, { id: 2, categories: [{ title: "Electronics" }] } ] }; const filtered = component.filterProducts(); expect(filtered).toEqual([{ id: 2, categories: [{ title: "Electronics" }] }]);
6. 边界场景:选中类别未定义/为空字符串
If your component allows chosenCategory to be undefined or an empty string, test how the function reacts (it should only return products with a matching empty title, which is probably none in most cases).
component.state = { chosenCategory: "", products: [ { id: 1, categories: [{ title: "Electronics" }] }, { id: 2, categories: [{ title: "" }] } ] }; const filtered = component.filterProducts(); expect(filtered).toEqual([{ id: 2, categories: [{ title: "" }] }]);
优化建议:改成纯函数(可选但推荐)
Right now, your function depends on this.state, which ties it to the component instance. To make testing even easier, refactor it into a pure function that accepts products and chosenCategory as arguments:
// 重构后的纯函数 filterProducts = (products, chosenCategory) => { return products.filter(product => product.categories.some(cat => cat.title === chosenCategory) ); };
Testing this is simpler—no need to mock a component instance:
const testProducts = [/* 测试产品数组 */]; const result = filterProducts(testProducts, "Electronics"); expect(result).toEqual(/* 预期结果 */);
Pure functions are easier to test, debug, and reuse—win-win!
内容的提问来源于stack exchange,提问作者The Walrus

