无法使用Jest对带有选择器功能的redux-saga进行单元测试

时间:2017-12-05 11:26:54

标签: javascript unit-testing react-redux jest redux-saga

问题说明:

我想使用Jest对redux-saga进行单元测试。我按照redux-saga文档中提供的示例中描述的方式执行此操作:https://redux-saga.js.org/docs/advanced/Testing.html

在我的Saga中,我正在调用一个选择器函数export const selectSet = state => state.setStore.set ,它从应用程序商店返回一个特定的对象:

import { put, select } from 'redux-saga/effects'
import { selectSet } from '../selectors'

export function* getSet() {
  try {
    const set = yield select(selectSet)
    yield put({ type: 'SET_SUCCESS', payload: { set } })
  } catch (error) {
    yield put({ type: 'SET_ERROR', payload: { error } })
  }
}

在我的传奇中,我试图产生这个选择器功能:

import assert from 'assert'
import * as AppRoutines from './AppRoutines'
import { put, select } from 'redux-saga/effects'

describe('getSet()', () => {
    it('should trigger an action type "SET_SUCCESS" with a payload containing a valid set', () => {
        const generator = AppRoutines.getSet()

        const set = {
          id: 1,
          slots: [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }],
        }

        const selectSet = jest.fn()
        selectSet.mockReturnValue(set)

        // Saga step 1
        const actualFirst = generator.next().value
        const expectedFirst = select(selectSet)

        assert.deepEqual(
          actualFirst,
          expectedFirst,
          'it should retreive a valid set from the store using the selectSet selector'
        )
    })
})

在我的测试中,没有有效的应用程序存储,所以我必须模拟该函数以返回预期的对象:

deepEqual

但是 - 如果我断言saga使用selectSet和我的模拟函数返回特定的生成器值,它期望我的选择器函数具有原始的mockConstructor构造函数。但是因为我用jest.fn()来模拟函数,所以构造函数实际上等于Expected value to deeply equal to: {"@@redux-saga/IO": true, "SELECT": {"args": Array [], "selector": [Function mockConstructor]}} Received: {"@@redux-saga/IO": true, "SELECT": {"args": Array [], "selector": [Function selectSet]}} - 这使得我的测试失败了:

mockConstructor

问题:如何在没有冲突的构造函数类型的情况下创建包含模拟函数的assert.deepEqual?

备选问题:有没有办法让我的断言期望selectSet而不是实际的--out rspec_results.html构造函数?

2 个答案:

答案 0 :(得分:4)

你根本不需要模拟选择器,就像在这种性质的传奇测试中一样,选择器实际上从未被调用,而是你正在测试为redux saga中间件创建的声明性指令。你期待

这是saga将创建{"@@redux-saga/IO": true, "SELECT": {"args": Array [], "selector": [Function selectSet]}}的指令,但由于在此测试场景中中间件未运行selectSelect将永远不会被调用

如果您需要模拟选择器为您的操作返回的结果,那么您可以将模拟数据传递到下一步...

    const set = {
      id: 1,
      slots: [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }],
    }

    // Saga step 1
    const firstYield = generator.next().value
    assertDeepEqual(firstYield, select(selectSet))

    // Step 2 - successful so dispatch action
    // mock data from the previous yield by passing into this step via `next(stubbedYieldedData)`
    const secondYield = generator.next(set).value
    assertDeepEqual(secondYield, put({type: 'SET_SUCCESS', payload: {set} }))

答案 1 :(得分:4)

我们可以通过以下方式在假商店中通过模拟商店。下面是示例选择器和生成器功能及其测试。

选择器

CarouselView

传奇发生器功能

CarouselView

测试用例

const authSelector = (state) => state.authReducer || initialState;