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

标签 javascript unit-testing react-redux jestjs redux-saga

问题说明:

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

在我的 Saga 中,我正在调用一个选择器函数 selectSet,它从应用程序商店返回一个特定的对象:

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'
        )
    })
})

但是 - 如果我断言 saga 使用 deepEqual 和我的模拟函数返回特定的生成器值,它期望我的选择器函数具有原始的 selectSet 构造函数。但是由于我用 jest.fn() 模拟函数,构造函数实际上等于 mockConstructor - 这使我的测试失败:

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]}}

问题:如何创建一个包含模拟函数的 assert.deepEqual 而不会产生冲突的构造函数类型?

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

最佳答案

您根本不需要模拟选择器,因为在这种性质的 saga 测试中,选择器从未真正被调用,相反,您正在测试为 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} }))

关于javascript - 无法使用 Jest 对具有选择器功能的 redux-saga 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47652514/

相关文章:

javascript - 如何向非 cocoa 应用程序添加 AppleScript/JXA 支持?

javascript - ReactJS View 处理具有不同数据的同一组件

unit-testing - 无法读取未定义单元测试 enzyme 的属性 'contextTypes'

Matlab 从 XUnit 迁移到 Matlab 2013 单元测试

react-native - react 原生 redux 和 ListView

javascript - 三个 JS 创建自定义形状几何体

php - 是否可以在同一页面上使用两个 Facebook 应用程序,或者将它们合并为一个?

javascript - 在文档正文内容周围包装一个 div

unit-testing - nUnit 测试相互依赖关系/层次结构

c# - 在 C# 中,如何对客户端用户交互和 javascript (jQuery) 代码进行单元测试?