有没有一种方法可以正确模拟重新选择选择器以进行单元测试?

Eug*_*akh 3 javascript unit-testing jestjs reselect

我的项目中有一个非常复杂的选择器结构(一些选择器可能具有多达5个嵌套层),因此其中一些很难通过传递输入状态进行测试,而我想模拟输入选择器。但是我发现这是不可能的。

这是最简单的示例:

// selectors1.js
export const baseSelector = createSelector(...);
Run Code Online (Sandbox Code Playgroud)

--

// selectors2.js
export const targetSelector = createSelector([selectors1.baseSelector], () => {...});
Run Code Online (Sandbox Code Playgroud)

我想在测试套件中拥有什么:

beforeEach(() => {
  jest.spyOn(selectors1, 'baseSelector').mockReturnValue('some value');
});

test('My test', () => {
  expect(selectors2.targetSelector()).toEqual('some value');
});
Run Code Online (Sandbox Code Playgroud)

但是,这种方法将无法像在初始化期间targetSelector获得引用那样工作selectors1.baseSelectorselectors2.js并且在模拟selectors1.baseSelector之后将其分配给它。

我现在看到2种可行的解决方案:

  1. 用来模拟整个selectors1.js模块jest.mock,但是,如果我需要在selectors1.baseSelector某些特定情况下更改输出,它将无法正常工作
  2. 像这样包装每个依赖选择器:

export const targetSelector = createSelector([(state) => selectors1.baseSelector(state)], () => {...});
Run Code Online (Sandbox Code Playgroud)

但是出于显而易见的原因,我不太喜欢这种方法。

因此,接下来的问题是:是否有机会模拟重新选择选择器以进行单元测试?

Mac*_*ora 5

The thing is that Reselect is based on the composition concept. So you create one selector from many others. What really you need to test is not the whole selector, but the last function which do the job. If not, the tests will duplicate each other, as if you have tests for selector1, and selector1 is used in selector2, then automatically you test both of them in selector2 tests.

In order to achieve:

  • less mocks
  • no need to specially mock result of composed selectors
  • no test duplication

test only the result function of the selector. It is accessible by selector.resultFunc.

So for example:

const selector2 = createSelector(selector1, (data) => ...);

// tests

const actual = selector2.resultFunc([returnOfSelector1Mock]);
const expected = [what we expect];
expect(actual).toEqual(expected)
Run Code Online (Sandbox Code Playgroud)

Summary

Instead of testing the whole composition, and duplicating the same assertion, or mocking specific selectors outputs, we test the function which defines our selector, so the last argument in createSelector, accessible by resultFunc key.