如何使用 redux-saga-test-plan 测试选择器功能

Posted

技术标签:

【中文标题】如何使用 redux-saga-test-plan 测试选择器功能【英文标题】:How to test selector function with redux-saga-test-plan 【发布时间】:2022-01-08 22:16:15 【问题描述】:

我正在测试我的 redux-saga-flow,但在使用 select 测试选择器方法时遇到问题。

选择器

const selector = (state) => 
   console.log("selector");
   return data;

Redux 传奇流程

export function* testedSagaFlow() 
  const data = yield select(selector);
  if (!data) 
    return;
  
  yield put (otherAction)
  ...

流量测试

test("Get data from store", () => 
  return expectSaga(testedSagaFlow)
  .provide([[mathchers.select.selector(selector), null]])
  .select(selector)
  .not.put(otherAction)
  .run()
)

运行测试后,没有console.log("selector");,而且这行代码也没有被测试覆盖。

如何测试选择器?

同样不适用于单元测试。

test("Unit test flow", () => 
   const saga = testSaga(testedSagaFlow);
   saga
    .next()
    .select(selector)
    .next(null)
    .isDone()
)

【问题讨论】:

【参考方案1】:

"redux-saga-test-plan": "^4.0.1".

选项 1. 使用 withState:

对于静态,您可以只使用withState 方法让select 效果起作用。

选项 2。使用static provider

您可以通过静态提供程序以简洁的方式提供模拟值。将一组元组对(数组对)传入provide 方法。对于每一对,第一个元素应该是匹配效果的匹配器,第二个效果应该是您要提供的模拟值。

例如

saga.ts:

import  put, select  from 'redux-saga/effects';

const otherAction =  type: 'OTHER_ACTION' ;

export const selector = (state) => 
  console.log('selector');
  return state.data;
;

export function* testedSagaFlow() 
  const data = yield select(selector);
  if (!data) 
    return;
  
  yield put(otherAction);

saga.test.ts:

import  expectSaga  from 'redux-saga-test-plan';
import  select  from 'redux-saga/effects';
import  selector, testedSagaFlow  from './saga';

describe('70199170', () => 
  test('should dispatch other action', () => 
    const state =  data: true ;
    return expectSaga(testedSagaFlow).withState(state).put( type: 'OTHER_ACTION' ).run();
  );

  test('should return if data is nil', () => 
    const state =  data: null ;
    return expectSaga(testedSagaFlow).withState(state).not.put( type: 'OTHER_ACTION' ).run();
  );
);

describe('70199170 - use provider', () => 
  test('should dispatch other action', () => 
    return expectSaga(testedSagaFlow)
      .provide([[select(selector), true]])
      .put( type: 'OTHER_ACTION' )
      .run();
  );

  test('should return if data is nil', () => 
    return expectSaga(testedSagaFlow)
      .provide([[select(selector), null]])
      .not.put( type: 'OTHER_ACTION' )
      .run();
  );
);

测试结果:

 PASS   redux-saga-examples  packages/redux-saga-examples/src/***/70199170/saga.test.ts
  70199170
    ✓ should dispatch other action (30 ms)
    ✓ should return if data is nil (4 ms)
  70199170 - use provider
    ✓ should dispatch other action (2 ms)
    ✓ should return if data is nil (3 ms)

  console.log
    selector

      at selector (packages/redux-saga-examples/src/***/70199170/saga.ts:6:11)

  console.log
    selector

      at selector (packages/redux-saga-examples/src/***/70199170/saga.ts:6:11)

Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total
Snapshots:   0 total
Time:        2.934 s, estimated 3 s
Ran all test suites related to changed files.

【讨论】:

谢谢。我稍后会尝试这个解决方案。以及您可以使用 testSaga()? 对单元测试提出什么建议 解决这个问题只有一种方法?我的意思是,在我的示例中,我使用提供者和模拟数据作为元组中的第二个参数。 @ElliZorro 更新答案,使用static provider添加测试套件 我使用"redux-saga-test-plan": "4.0.3",只有第一个解决方案对我有用:(

以上是关于如何使用 redux-saga-test-plan 测试选择器功能的主要内容,如果未能解决你的问题,请参考以下文章

Redux Saga:使用 redux-saga-test-plan 和 jest 在我的 saga 中测试纯 javascript 函数

我的减速机应该处理@@ redux-saga-test-plan / INIT动作吗?

redux-saga-test-plan put 效果不匹配,但实际和预期的有效负载相等

[精选] Mysql分表与分库如何拆分,如何设计,如何使用

如果加入条件,我该如何解决。如果使用字符串连接,我如何使用

如何使用本机反应创建登录以及如何验证会话