我们看到的大多数教程都会讲单元测试的重要性、一些有代表性的测试框架 api 怎么使用,但在实际项目中单元测试要怎么下手?测试用例应该包含哪些具体内容呢?...单元测试部分介绍 先讲一下用到了哪些测试框架和工具,主要内容包括: jest ,测试框架 enzyme ,专测 react ui 层 sinon ,具有独立的 fakes、spies、stubs、mocks...sagas 这里我用了 redux-saga 处理业务流,这里具体也就是异步调用 api 请求数据,处理成功结果和错误结果等。...如果错误返回,则发送错误 action 通知 reducer。 那么具体的测试用例应该怎么写呢?...这也是我选择 redux-saga 的原因:强大并且利于测试。 api 和 fetch 工具库 接下来就是api 层相关的了。
action 测试 reducer 测试 selector 测试 saga 测试 来自官方的错误姿势 正确姿势 component 测试 业务型组件-分支渲染 业务型组件-事件调用 功能型组件-children...connect 组件里套 @connect组件的场景); 牺牲了开发体验,搞起来没那么快了; 收益只是可能覆盖到了几个偶尔出现的场景(比如接入错误的字段、写字段时写错等); 关于 UI 测试策略:团队之前尝试过...Emit 的事件、需要保存到 IndexDB 中去的数据等) 来自官方的错误姿势 redux-saga 官方提供了一个 util: CloneableGenerator用以帮我们写 saga 的测试。...基于这个发现,我们推出了我们的第二版 saga 测试方案:runSaga + 自定义拓展 jest 的 expect 断言。...中取得了正确的参数 map 过的 props 是否正确地被传递给了组件 redux 对应的数据切片更新时,是否会使用新的 props 触发组件进行一次更新 这四个点,react-redux 已经都帮你测过了
放到 race 方法里以自动取消 redux-saga 使用了 ES6 的 Generator 功能,让异步的流程更易于读取,写入和测试。.../sagas 模块中的 Saga。然后使用 redux-saga 模块的 createSagaMiddleware 工厂函数来创建一个 Saga middleware。...redux-saga 使用 PUT 来描述dispatch 一个 action 到 Store 而不是直接dispatch action 的原因也是为了方便测试。...这个 effect 是非阻塞型的,并且所有向下游抛出的错误(例如在 reducer 中),都不会冒泡回到 saga 当中。...Effect 是使用 redux-saga 提供的工厂函数创建的。
redux异步流中间件其实有很多,当下主流的异步中间件有两种redux-thunk、redux-saga。...(1)使用react-thunk中间件redux-thunk优点:体积⼩: redux-thunk的实现⽅式很简单,只有不到20⾏代码使⽤简单: redux-thunk没有引⼊像redux-saga或者...该action的函数体会自动执行 store.dispatch(action)}(2)使用redux-saga中间件redux-saga优点:异步解耦: 异步操作被被转移到单独 saga.js 中...⽤灵活: redux-saga可以将多个Saga可以串⾏/并⾏组合起来,形成⼀个⾮常实⽤的异步flow易测试,提供了各种case的测试⽅案,包括mock task,分⽀覆盖等等redux-saga缺陷:...⽤到,但是我们依然需要引⼊这些代码ts⽀持不友好: yield⽆法返回TS类型redux-saga可以捕获action,然后执行一个函数,那么可以把异步代码放在这个函数中,使用步骤如下:配置中间件import
否则会出现惊喜 call generator 只能接受到返回值 redux-saga初使用 安装: yarn add redux-saga store.js import { createStore...from 'redux-saga'; // 导入创建saga的函数 import {add, deleter} from '....// 查询store的状态 takeEvery // 对action进行监听 } from 'redux-saga/effects'; export function* fetchData...的第一个参数则触发 fetchData这个函数 export function* watch() { yield takeEvery('fetchData', fetchData); } 正常使用...调用其他函数 调用的函数可以是Generator 或者是返回一个promise的简单函数 call函数页数阻塞effect select 解释: select函数是用来指示middleware调用提供的选择器获取
当用户导航到另一个URL时,需要刷新整个页面,服务器为新页面发送新的HTML。这称为服务器端呈现。 但是在现代的SPAs中,使用的是客户端呈现。...最终,一个明显的赢家出现了,那就是Redux。Redux结合了Flux、Command pattern和Elm体系结构的思想,是目前开发人员与React一起使用的事实上的状态管理库。...Jest可以保存React组件和Redux状态生成的输出,并将其保存为序列化文件,这样您就不必自己手动生成预期的输出。Jest还具有内置的模拟、断言和测试覆盖率。一个图书馆来统治他们所有人!...Jest和酶使编写前端测试变得有趣和容易。因为定义了明确的职责和接口,所以React组件和Redux操作/缩减器相对容易测试也很有帮助。...在大多数情况下,使用ESLint就像调整项目文件夹中的配置文件一样简单。如果您不为ESLint编写新的规则,那么就没有什么可学习的。当错误出现时,请注意它们,并将其谷歌,以找到推荐的样式。
因此我们的测试必须减少共享状态来提高并发能力,不然就会出现意想不到的错误。安装和运行: yarn add ava ava --watch 这样可以运行并watch测试。...改变代码测试结果会立刻改变,你也可以看到友善的错误信息,以及expected和actual之间的diff。...Facebook自家的Jest对snapshot的支持更好,当snapshot不匹配时按个y/n就完事了,够快了吧。...我们用一个叫做Redux-saga的库来展现全家桶的异步测试怎么写,Redux模仿的目标是Elm architecture,但是简化掉了Elm的作用模型,只保留了同步模型,Redux-saga其实就是把...其他部分都可以开心地发同步事件了,此外有了Saga之后Redux终于有了“用事件触发事件”的机制了,只用redux,应用复杂到一定程度你一定会想这个问题的。
截止至本文发布时,原仓库已经有了中文版,大家可自行选择查阅,由于是 roadmap 的聚合类列表,所以翻译方面差异不会很大。 学习路线图 ?...·学习 HTML 基础 ·写些页面作为练习 ii.CSS ·学习 CSS 基础 ·在上一步练习的基础上为页面添加样式 ·使用...Saga ·Redux Observable b.数据持久化 ·Redux Persist ·Redux Phoenix...i.单元测试 ·Jest ·Enzyme ·Sinon ·Mocha ·Chai ·AVA ·Tape ii.端到端测试...参与贡献 学习路线图是使用 Draw.io 画的。文件就放在 /src 目录下。想要修改思维导图,先打开 draw.io ,点击 Open Existing Diagram 然后选择 xml 文件。
Jest Snapshot Test的特点: Jest 使用一个 test renderer 来生成出 React tree 的序列化结构树。...Jest 的 snapshot 测试不仅可以对比React tree结构的区别, 也可以对比其他可序列化的值的区别。 比如对比Redux某个状态的state是否和之前相同。...当 snapshot 结果需要升级更新时, 只需要执行 jest -u 指令即可更新之前生成的 snapshot 结果。 为什么 Snapshot 在 React 测试中是可靠的呢?...这样的好处是当 PrimaryButton 自身出现bug时, 之后这个组件本身的单元测试会 fail, 其他用到这个组件的 Component 并不会受影。 这样测试之间就相互独立了。...举个例子, 有reducer如下(我们在redux中使用了Immutable.js): // reducer export function localUserReducer(state, action
Redux-Saga比Redux-Thunk复杂得多,而且他整个异步流程都使用Generator来处理,Generator也是我们这篇文章的前置知识,如果你对Generator还不熟悉,可以看看这篇文章...也就是说,当你这样写时: yield take("SOME_ACTION"); yield fork(saga); 当运行到yield take("SOME_ACTION");这行代码时,整个迭代器都阻塞了...effect时,他的返回值就仅仅是一个描述当前任务的对象,这就让我们的单元测试好写很多。...因为我们的代码在不同的环境下运行可能会产生不同的结果,特别是这些异步请求,我们写单元测试时来造这些数据也会很麻烦。...但是如果你使用Redux-Saga的effect,每次你代码运行的时候得到的都是一个任务描述对象,这个对象是稳定的,不受运行结果影响,也就不需要针对这个造测试数据了,大大减少了工作量。
on the Saga concept 三.核心实现 利用generator,让异步流程控制易读、优雅、易测试 In redux-saga, Sagas are implemented using Generator...所以添一层描述对象来解决这个问题,测试case中可以简单比较描述对象,实际起作用的Promise由redux-saga内部生成 这样做的好处是单测中不用mock异步方法(一般单测中会把所有异步方法替换掉...(不用mock异步函数),这不很过分 注意,不需要mock异步函数只是简化了单元测试的一个环节,即便使用这种对比描述对象的方式,仍然需要提供预期的数据,例如: // 测试场景直接执行 const iterator...error的传递方式,所以如果任一task有未捕获的error,当前saga也会结束 另外,cancel机制比较有意思: 对于执行中的task序列,所有task自然完成时,把结果向上传递到队首,作为上层某个...,提供了各种case的测试方案,包括mock task,分支覆盖等等 大而全的异步控制库,从异步流程控制到并发控制应有尽有 完备的错误捕获机制,阻塞型错误可try-catch,非阻塞型会通知所属Saga
为了解决这个问题,redux建议使用中间件(尤其是thunk)。...使用这个方式会很快导致action生成方法变得复杂并难以测试。这个时候就需要redux-saga了。在redux-saga里saga就是一个可声明的组织良好的副作用实现方式(超时,API调用等等。。)...我(作者)更加倾向于把整个generator叫做纯generator,因为它不会实际执行副作用,只会生成一个要执行的副作用的描述。...现在,测试这个saga就非常的容易了: import { call, put } from 'redux-saga'; const mySaga = loadTodos(); const myTodos...它是一个简单可测试的方法: const render = (state) => components 组件会触发修改store的action。 state使用reducer这样的纯方法来修改的。
可以看到,在整个流程中数据都是单向流动的,这种方式保证了流程的清晰。 redux原理详解 react-redux是如何工作的?...redux-thunk优点: 体积小: redux-thunk的实现方式很简单,只有不到20行代码 使用简单: redux-thunk没有引入像redux-saga或者redux-observable额外的范式...实现,代码异常/请求失败 都可以直接通过 try/catch 语法直接捕获处理 功能强大: redux-saga提供了大量的Saga 辅助函数和Effect 创建器供开发者使用,开发者无须封装或者简单封装即可使用...灵活: redux-saga可以将多个Saga可以串行/并行组合起来,形成一个非常实用的异步flow 易测试,提供了各种case的测试方案,包括mock task,分支覆盖等等 redux-saga缺陷...: 额外的学习成本: redux-saga不仅在使用难以理解的 generator function,而且有数十个API,学习成本远超redux-thunk,最重要的是你的额外学习成本是只服务于这个库的
通过导入 regenerator-runtime/runtime 允许 Babel 进行异步动作的转译,而不会出现任何问题。...如果忽略此行,则你的应用会失败,并显示以下错误消息:Uncaught ReferenceError:regeneratorRuntime is not defined。...这使我们可以将 saga 和 reducers 并置在使用它们的组件附近。这也使它们易于管理,因为它们仅包含与附近文件相关的代码。 在例子中,exampleSaga只是执行一次并终止的普通函数。...我们将为多个中间件使用一个中间件数组。...Redux-Saga 配置 Store 这是整合 redux-saga 之后我们最终 store 的配置。
依赖关系 dva react react-dom dva-core redux redux-saga history react-redux react-router-redux...model配置得到reducers,worker sagas, states后,屏蔽接下来的一系列繁琐工作: 接redux(组合state,组合reducer) 接redux-saga(完成redux-saga...的fork -> watcher -> worker,并做好错误捕获) 除了core里最重要的两部分外,dva还做了一些事情: 内置react-router-redux, history负责路由管理 粘上...级hook),让内部状态可读 提供全局错误处理方式,解决异步错误不可控的痛点 增强model管理(允许动态增删model) 猜测整个实现过程是这样: 配置化 在技术上实现固化,把灵活性限制起来,让业务写法更统一...和redux-saga通过model配置整合起来,并增强一些控制(错误处理等),引入的唯一外来概念是subscription,还挂在model上,即便用力设计API,也复杂不到哪去 四.优缺点 有什么缺点
state 做改变,而是通过 action 来改变 setMessageAction (newValue) { // 因为都走action,就可以知道到底改变(mutation)是如何被触发的,出现错误...redux Redux使用一个对象存储整个应用的状态(global state),当global state发生变化时,状态从树形结构的最顶端往下传递。每一级都会去进行状态比较,从而达到更新。...关于saga原理的,推举阅读《前端技术栈(三):redux-saga,化异步为同步》 什么是Saga?...redux-saga 采用了另外一种思路,它没有把异步操作放在 action creator 中,也没有去处理 reductor,而是把所有的异步操作看成“线程”,可以通过普通的action去触发它,当操作完成时也会触发...redux-saga 把异步获取数据这类的操作都叫做副作用(Side Effect),它的目标就是把这些副作用管理好,让他们执行更高效,测试更简单,在处理故障时更容易。
文章目录 资料 redux-saga简介 常用API takeLatest takeEvery take delay put call fork cancel all 案例1:错误处理了 案例2:错误未处理...6979146131028574245 redux-saga简介 使用 dispatch 往 store 发送 action 的这个过程是可以被拦截的, 自然而然地就可以在这里增加各种中间件Middleware...Effects是一些简单对象,如下put({ type: ‘increment’ }),我们使用redux-saga提供的put方法创建一个Effect对象。...使用all并发启动阻塞任务task1与task2 const res = yield all([call(task1), call(task2)]) // 2,当all接受到结果时输出结果,但是由于task1...使用all并发启动阻塞任务task1与task2 const res = yield all([call(task1), call(task2)]) // 2,当all接受到结果时输出结果,但是由于task1
如果不需要支持低版本 IE 的话,我们主要使用 React: React – 编写页面组件 Redux – 数据流和状态管理,一般结合 redux-saga 使用 React-router v4 – 前端路由管理...(Note:dva 整合了 redux, redux-router 以及 redux-saga。...在熟悉了基本的 Redux, Redux-saga, Redux-router 的使用之后,可以尝试用 dva 替代) Webpack – 前端构建工具 用到的其他类库,技术选择和工具 前端开发我在用到的其他类库...AutoPrefixer – PostCSS 插件,构建时根据 caniuse-lite 数据库以及你设置的或者默认的浏览器列表(browserslist)给 CSS 属性自动增加浏览器厂商前缀。...Ava, Chai.js, Jest, Enzyme, Headless Chrome – 测试框架,runner,断言库,单元测试,组件测试,端对端测试的一些工具。
如果你希望单元测试所测试的 Order 模块是独立的,那么你就不想直接使用真正的 Product 或 Customer Class,因为 Customer Class 的错误会直接导致 Order Class...}; }); }); 我们可以看到 jest.mock() 方法中的第二个参数是一个函数,那么我们就可以完全接管整个 ....“知道”在结束时进行断言。...React 组件测试 组件化与 UI 测试 image.png 在组件化出现之前,我们都压根不谈 UI 的单元测试,哪怕是对于 UI 页面层级的测试来说都是一件非常困难的事情。...,其实我们在测试 React 组件(单元)的时候不需要关心 Redux store 长什么样子,我们只需要知道 Redux store 当中的这些 action 将会在适当的时机触发,以及它们触发时的预期行为是什么
这些 action 来控制 state 的改变,也就是不直接去对 state 做改变,而是通过 action 来改变,因为都走 action,我们就可以知道到底改变(mutation)是如何被触发的,出现错误...所以大家在使用的时候,一般会用 Redux,他和 Flux 思想比较类似,也有差别。 Store Redux 里面只有一个 Store,整个应用的数据都在这个大 Store 里面。...redux-saga 把异步获取数据这类的操作都叫做副作用(Side Effect),它的目标就是把这些副作用管理好,让他们执行更高效,测试更简单,在处理故障时更容易。...而且很容易测试到不同的分支。 这里不讨论更多 saga 的细节,大家了解 saga 的思想就行,细节请看文档。...如果使用 Dva,那么结构图如下: 整个结构变化不大,最主要的就是把 store 及 saga 统一为一个 model 的概念(有点类似 Vuex 的 Module),写在了一个 js 文件里。