[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 ...
随机推荐
- POJ-1001 Exponentiation 高精度算法
题目链接:https://cn.vjudge.net/problem/POJ-1001 以前写过一个高精度乘法,但是没有小数点,实现起来也没什么难得, 现在把代码都般过来,等会把旧电脑弄一弄,暂时就不 ...
- Spring MVC框架一个实例的手动实现
文件结构: SpringMVC05 // 应用程序名 ----index.html // 欢迎文件,主目录下的文件可以被URL直接访问到 ----WEB-INF // 这个目录下的文件将被保护起来不能 ...
- Linux 部署项目经验总结
[通用命令] 1.创建文件夹 mkdir -p xxx 2.解压包 tar -zxvf xxxx.tar.gz 3.缩文件 tar zcvf 压缩包名称.tar.gz 要压缩的文件 4.动命令 ...
- Zookeeper入门:基本概念、5项配置、启动
起源 最早接触Zookeeper,是在学习Hadoop权威指南这本书的时候,印象中是Hadoop项目的一个子工程. 最近,项目中需要用到"分布式锁". 之前,在 ...
- Object-C,循环语句for,while,do-while
演示循环语句,for,while,do-while,和C系列的语言,语法基本一致1到10,求和 // // main.m // for-while // // Created by fansunion ...
- iOS数字媒体开发浅析
概述 自然界中的所有看到的听到的都是模拟信号,模拟信号是随时间连续变化,然而手机电脑等信息都属于数字媒体,它们所呈现的内容就是把自然界中这些模拟信号转换成数字信号然后再传递给我们.数字信号不是连续的是 ...
- POJ 2826 An Easy Problem!(简单数论)
Description Have you heard the fact "The base of every normal number system is 10" ? Of co ...
- JAVA 不同类载入器命名空间的理解
曾经一直有这样一个疑惑: 都说在JAVA中,由不同类载入器载入的类在虚拟机中位于不同的命名空间下,不同命名空间下的类相互不可见. 这让我产生了一个迷惑:假设有一个类A使用了ja ...
- iOS经常使用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)
1. 简单工厂模式 怎样理解简单工厂,工厂方法. 抽象工厂三种设计模式? 简单工厂的生活场景.卖早点的小摊贩.他给你提供包子,馒头,地沟油烙的煎饼等,小贩是一个工厂.它生产包子,馒头,地沟油烙的煎饼. ...
- zzuli--1812--sort(模拟水题)
1812: sort Time Limit: 1 Sec Memory Limit: 128 MB Submit: 158 Solved: 30 SubmitStatusWeb Board Des ...