[Redux-Observable && Unit Testing] Use tests to verify updates to the Redux store (rxjs scheduler)
In certain situations, you care more about the final state of the redux store than you do about the particular stream of events coming out of an epic. In this lesson we explore a technique for dispatching actions direction into the store, having the epic execute as they would normally in production, and then assert on the updated store’s state.
To test a reducer, what we need to do is actually dispatch as action with its payload.
store.dispatch(action);
But before that, we need to get our 'store' configuration in the test.
configureStore.js:
import {createStore, applyMiddleware, compose} from 'redux';
import reducer from './reducers';
import { ajax } from 'rxjs/observable/dom/ajax'; import {createEpicMiddleware} from 'redux-observable';
import {rootEpic} from "./epics/index"; export function configureStore(deps = {}) {
const epicMiddleware = createEpicMiddleware(rootEpic, {
dependencies: {
ajax,
...deps
}
}); const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; return createStore(
reducer,
composeEnhancers(
applyMiddleware(epicMiddleware)
)
);
}
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import {Provider} from 'react-redux';
import {configureStore} from "./configureStore"; const store = configureStore(); ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, document.getElementById('root'));
The configureStore.js exports function which create a store, we can import normally in the test file.
Now for example, we want to dispatch this action:
export function searchBeers(query) {
return {
type: SEARCHED_BEERS,
payload: query
}
}
Epic:
import {Observable} from 'rxjs';
import {combineEpics} from 'redux-observable';
import {CANCEL_SEARCH, receiveBeers, searchBeersError, searchBeersLoading, SEARCHED_BEERS} from "../actions/index"; const beers = `https://api.punkapi.com/v2/beers`;
const search = (term) => `${beers}?beer_name=${encodeURIComponent(term)}`; export function searchBeersEpic(action$, store, deps) {
return action$.ofType(SEARCHED_BEERS)
.debounceTime(500)
.filter(action => action.payload !== '')
.switchMap(({payload}) => { // loading state in UI
const loading = Observable.of(searchBeersLoading(true)); // external API call
const request = deps.ajax.getJSON(search(payload))
.takeUntil(action$.ofType(CANCEL_SEARCH))
.map(receiveBeers)
.catch(err => {
return Observable.of(searchBeersError(err));
}); return Observable.concat(
loading,
request,
);
})
} export const rootEpic = combineEpics(searchBeersEpic);
'decountTime' make the Epic async!
To verifiy the result is correct, we can do
const store = configureStore(deps); const action = searchBeers('name'); store.dispatch(action); expect(store.getState().beers.length).toBe();
BUT, actually this test code won't work, because the 'decountTime' in the epic, makes it as async opreation. Reducer expects everything happens sync...
One way can test it by using 'scheduler' from rxjs.
import {Observable} from 'rxjs';
import {VirtualTimeScheduler} from 'rxjs/scheduler/VirtualTimeScheduler';
import {searchBeers} from "../actions/index";
import {configureStore} from "../configureStore"; it('should perform a search (redux)', function () { const scheduler = new VirtualTimeScheduler();
const deps = {
scheduler,
ajax: {
getJSON: () => Observable.of([{name: 'shane'}])
}
}; const store = configureStore(deps); const action = searchBeers('shane'); store.dispatch(action); scheduler.flush(); expect(store.getState().beers.length).toBe();
});
And we need to modifiy the epic:
.debounceTime(, deps.scheduler)
Take away, we can test async oprations by using 'scheduler' from rxjs.
-------------------FUll Code------------
[Redux-Observable && Unit Testing] Use tests to verify updates to the Redux store (rxjs scheduler)的更多相关文章
- Unit Testing with NSubstitute
These are the contents of my training session about unit testing, and also have some introductions a ...
- [Java Basics3] XML, Unit testing
What's the difference between DOM and SAX? DOM creates tree-like representation of the XML document ...
- Unit Testing PowerShell Code with Pester
Summary: Guest blogger, Dave Wyatt, discusses using Pester to analyze small pieces of Windows PowerS ...
- C# Note36: .NET unit testing framework
It’s usually good practice to have automated unit tests while developing your code. Doing so helps y ...
- Unit Testing of Spring MVC Controllers: “Normal” Controllers
Original link: http://www.petrikainulainen.net/programming/spring-framework/unit-testing-of-spring-m ...
- Unit Testing, Integration Testing and Functional Testing
转载自:https://codeutopia.net/blog/2015/04/11/what-are-unit-testing-integration-testing-and-functional- ...
- Javascript单元测试Unit Testing之QUnit
body{ font: 16px/1.5em 微软雅黑,arial,verdana,helvetica,sans-serif; } QUnit是一个基于JQuery的单元测试Uni ...
- [Unit Testing] AngularJS Unit Testing - Karma
Install Karam: npm install -g karma npm install -g karma-cli Init Karam: karma init First test: 1. A ...
- C/C++ unit testing tools (39 found)---reference
http://www.opensourcetesting.org/unit_c.php API Sanity AutoTest Description: An automatic generator ...
随机推荐
- [洛谷P2085]最小函数值
题目大意:有n个函数,分别为F1,F2,...,Fn.定义Fi(x)=Ai*x^2+Bi*x+Ci (x∈N*).给定这些Ai.Bi和Ci,要求出所有函数的所有函数值中最小的m个(如有重复的要输出多个 ...
- 洛谷 P1273 有线电视网 && caioj 1109 树形动态规划(TreeDP)4:比赛转播(树上分组背包总结)
从这篇博客往前到二叉苹果树都可以用分组背包做 这依赖性的问题,都可以用于这道题类似的方法来做 表示以i为根的树中取j个节点所能得的最大价值 那么每一个子树可以看成一个组,每个组里面取一个节点,两个节点 ...
- P2420 让我们异或吧(树链剖分)
题目描述 异或是一种神奇的运算,大部分人把它总结成不进位加法. 在生活中-xor运算也很常见.比如,对于一个问题的回答,是为1,否为0.那么: (A是否是男生 )xor( B是否是男生)=A和B是否能 ...
- PKU 2288 Islands and Bridges 状态dp
题意: 给你一张地图,上面有一些岛和桥.你要求出最大的三角哈密顿路径,以及他们的数量. 哈密顿路:一条经过所有岛的路径,每个岛只经过一次. 最大三角哈密顿路:满足价值最大的哈密顿路. 价值计算分为以下 ...
- 用Google Chrome 浏览器打开Unity打包的WebGL
方法一: 直接build and run 方法二: 步骤: 1.打开浏览器的属性 2.在目标的位置添加--allow-file-access-from-files, 注意--allow-file-ac ...
- 题解 P2910 【[USACO08OPEN]寻宝之路Clear And Present Danger】
说起来这还是本蒟蒻学完Floyd之后做的第一道题. emm...这是一道裸题,题目大致是说有一堆岛,岛之间有海盗,因此每一条边都有一个危险指数(权重),然后给出一段必须经过的路线,求从一号小岛走到N号 ...
- 【SRM 716 DIV 1 A】 ConstructLCS
Problem Statement A string S is a subsequence of a string T if we can obtain S from T by erasing som ...
- ArcGIS api for javascript——地理处理任务-计算一个可视域
描述 本例展示了使用一个地理处理计算一个可视域(viewshed) 单击地图上的任意点查看该点5英里内能看见的所有区域.这个模型需要几秒钟来运行并反馈结果. 可视域计算是通过ArcGIS Server ...
- ArcGIS api for javascript——以地理处理结果为条件查询地图
这里发生什么任务呢?当第一次单击地图,单击的坐标被发送到一个Geoprocessor任务.该任务访问服务器上的通过ArcGIS Server 地理处理服务提供的可用的GIS模型.本例中模型计算驱动时间 ...
- Qt 5.3 下OpenCV 2.4.11 开发(0)图像处理基本概念
1.普通情况下的RGB彩色图像:它的每一个像素点都是由三个通道组成,即红色(R).绿色(G)和蓝色(B).8位三通道彩色图像就是每一个像素中每一个通道的取值范围都是 0~255(即二进制下的8位数), ...