我的项目中有一个非常复杂的选择器结构(某些选择器可能最多有 5 层嵌套),因此其中一些很难通过传递输入状态进行测试,我想改为模拟输入选择器。然而我发现这实际上是不可能的。
这是最简单的例子:
// selectors1.js
export const baseSelector = createSelector(...);
-
// selectors2.js
export const targetSelector = createSelector([selectors1.baseSelector], () => {...});
我希望在我的测试套件中包含什么:
beforeEach(() => {
jest.spyOn(selectors1, 'baseSelector').mockReturnValue('some value');
});
test('My test', () => {
expect(selectors2.targetSelector()).toEqual('some value');
});
但是,这种方法不会起作用targetSelector
正在参考selectors1.baseSelector
在初始化期间selectors2.js
并且模拟被分配给selectors1.baseSelector
在它之后。
我现在看到有两个可行的解决方案:
- 模拟整个
selectors1.js
模块与jest.mock
,但是,如果我需要改变,那就行不通了selectors1.baseSelector
一些特定情况的输出
- 像这样包装每个依赖选择器:
export const targetSelector = createSelector([(state) => selectors1.baseSelector(state)], () => {...});
但出于显而易见的原因,我不太喜欢这种方法。
那么,接下来的问题是:是否有机会正确模拟 Reselect 选择器以进行单元测试?
问题是 Reselect 是基于组合概念的。因此,您可以从许多其他选择器中创建一个。您真正需要测试的不是整个选择器,而是完成这项工作的最后一个函数。如果没有,测试将相互重复,就好像您对选择器 1 进行了测试,而选择器 1 在选择器 2 中使用,那么您会自动在选择器 2 测试中测试它们。
为了要达到:
- 减少嘲笑
- 无需专门模拟组合选择器的结果
- 无重复测试
仅测试选择器的结果函数。可以通过以下方式访问selector.resultFunc
.
例如:
const selector2 = createSelector(selector1, (data) => ...);
// tests
const actual = selector2.resultFunc([returnOfSelector1Mock]);
const expected = [what we expect];
expect(actual).toEqual(expected)
Summary
我们不是测试整个组合,复制相同的断言,或者模拟特定的选择器输出,而是测试定义选择器的函数,因此 createSelector 中的最后一个参数可以通过resultFunc
key.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)