簡體   English   中英

無法使用 Jest 對帶有選擇器功能的 redux-saga 進行單元測試

[英]Can't unit test redux-saga with selector function using Jest

問題說明:

我想使用 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'
        )
    })
})

但是 - 如果我使用deepEqual和我的deepEqual函數斷言 saga 返回特定的生成器值,它希望我的選擇器函數具有原始的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} }))

我們可以在一個假商店中傳遞模擬商店,如下所示。 下面是示例選擇器和生成器函數及其測試。

選擇器

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

傳奇生成器功能

export function* getAuthToken(action) {
  try {
    const authToken = yield select(makeSelectAuthToken());
  } catch (errObj) {}
}

測試用例

    import { runSaga } from 'redux-saga'

    const dispatchedActions = [];

    const fakeStore = {
        getState: () => ({ authReducer: { auth: 'test' } }),
        dispatch: (action) => dispatchedActions.push(action)
      }

     await runSaga(fakeStore, getAuthToken, {
        payload: {}
     }).done;

expected case you can write here below this

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM