如何使用redux-saga-test-plan测试selector函数?
问题原因
你当前的saga测试不管是用expectSaga的provide模拟返回值,还是testSaga的步进测试,都默认跳过了selector的真实执行:测试框架只会验证你有没有调用select(selector)这个effect,不会真的运行传入的selector函数,所以自然看不到console.log输出,也不会统计到这部分代码的覆盖率。另外你提供的expectSaga测试代码里有拼写错误,mathchers应为matchers,拼写错误也会导致模拟逻辑不生效。
解决方案
方案1:单独编写Selector单元测试(最推荐)
Selector本身是无副作用的纯函数,完全可以脱离saga单独测试,逻辑清晰执行速度也最快:
test('selector 功能测试', () => { // 构造和业务逻辑匹配的模拟state const mockState = { data: '测试数据' // 其他selector依赖的state字段 } const result = selector(mockState) // 按业务需求加断言 expect(result).toBe('测试数据') })
该测试运行时会完整执行selector的所有代码,console.log会正常输出,也会被覆盖率统计覆盖。
方案2:在saga集成测试中真实触发selector执行
如果需要在saga流程测试中真实调用selector,不要用provide模拟select返回值,改用withState传入模拟的根state,测试库会自动调用selector从state中取值:
test("Get data from store", () => { const mockState = { // 传入和selector依赖匹配的state结构 data: null } return expectSaga(testedSagaFlow) .withState(mockState) .select(selector) .not.put(otherAction) .run() })
这种场景下selector会被真实执行,console.log和覆盖率统计都会正常生效。
方案3:testSaga步进测试补充selector校验
testSaga属于纯effect断言工具,本身不会执行任何业务逻辑,所以用这种测试方式时,单独补充selector的测试用例即可,不需要和saga流程绑定:
test("Unit test flow", () => { // 单独校验selector逻辑 const mockState = {data: null} expect(selector(mockState)).toBeNull() // 校验saga流程 const saga = testSaga(testedSagaFlow); saga .next() .select(selector) .next(null) .isDone() })
内容的提问来源于stack exchange,提问作者Elli Zorro
相关产品推荐
相关产品推荐

