[Redux-Observable && Unit Testing] Mocking an ajax request when testing epics
Often in unit tests we are focussing on the logic involved in crafting a network request, & how we respond to the result. The external service is unlikely to be under our control, so we need a way to ‘mock’ the Ajax request in a way that allows us to focus on the logic. In this lesson we’ll see how we can pass in dependencies into epics to make testing things Ajax requests easier.
In a real world React app, for one epic, we might have some dependecies. For example, ajax call. To make it easy for testing, we can make those deps as injectable deps.
When creating root epic:
import { createEpicMiddleware, combineEpics } from 'redux-observable';
import { ajax } from 'rxjs/observable/dom/ajax';
import rootEpic from './somewhere';
const epicMiddleware = createEpicMiddleware(rootEpic, {
dependencies: { getJSON: ajax.getJSON }
});
Using it in Epic:
// Notice the third argument is our injected dependencies!
const fetchUserEpic = (action$, store, { getJSON }) =>
action$.ofType('FETCH_USER')
.mergeMap(({ payload }) =>
getJSON(`/api/users/${payload}`)
.map(response => ({
type: 'FETCH_USER_FULFILLED',
payload: response
}))
);
---------------Test example ---------------------
index.js, root setup
import {createStore, applyMiddleware, compose} from 'redux';
import {Provider} from 'react-redux';
import reducer from './reducers';
import { ajax } from 'rxjs/observable/dom/ajax';
import {createEpicMiddleware} from 'redux-observable';
import {rootEpic} from "./epics/index";
const epicMiddleware = createEpicMiddleware(rootEpic, {
dependencies: {
ajax
}
});
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducer,
composeEnhancers(
applyMiddleware(epicMiddleware)
)
);
Epic function:
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(, deps.scheduler)
.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);
Test code:
import {Observable} from 'rxjs';
import {ActionsObservable} from 'redux-observable';
import {searchBeersEpic} from "./index";
import {RECEIVED_BEERS, searchBeers, SEARCHED_BEERS_LOADING} from "../actions/index";
it.only('should perform a search', function () {
const action$ = ActionsObservable.of(searchBeers('shane'));
const deps = {
ajax: {
getJSON: () => Observable.of([{name: 'shane'}])
}
};
const output$ = searchBeersEpic(action$, null, deps);
output$.toArray().subscribe(actions => {
expect(actions.length).toBe();
expect(actions[].type).toBe(SEARCHED_BEERS_LOADING);
expect(actions[].type).toBe(RECEIVED_BEERS);
});
});
Refs: Link
[Redux-Observable && Unit Testing] Mocking an ajax request when testing epics的更多相关文章
- Extjs4.0以上版本 Ext.Ajax.request请求的返回问题
Ext.Ajax.request({ url: posturl, method: 'POST', params: { ClassName: 'XXXX', FuncName: 'XXXX', para ...
- [转] form.getForm().submit的用法及Ext.Ajax.request的小小区别
原文地址:http://blog.csdn.net/hongleidy5000/article/details/7329325 if (!formDetail.getForm().isValid()) ...
- (ExtJs 3.4)Ext.Ajax.request的同步请求实现
ext3.0之前都是这样来提交:var responsea = Ext.lib.Ajax.getConnectionObject().conn;responsea.open("POST&qu ...
- Extjs-Ext.Ajax.request设置超时
ExtJs的Ajax提交主要是:Ext.Ajax.request或form1.getForm().submit,超时时间默认是30秒. 很多时候,后台处理比较多,往往需要超出30秒的限制.此时,可以通 ...
- EXTJS 资料 Ext.Ajax.request 获取返回数据
下面是一个登陆页面调用的EXTJS login function,通过 url: '/UI/HttpHandlerData/Login/Login.ashx',获取返回登陆账户和密码! Ext.onR ...
- Ext.Ajax.request()方法和FormPanel.getForm().submit()方法,都返回success()方法的差异
我还是不发表到博客园首页吧,要不然还是要被取消,>_< 还是言归正传吧,关于Ext.Ajax.request()方法和FormPanel.getForm().submit()方法返回suc ...
- 【转】Ext.ajax.request 中的success和failure
原文链接:Ext.ajax.request 中的success和failure Ajax request对象的success事件表示request过程中没有发生错误,和自己的业务逻辑无关, 如果访问不 ...
- Ext.Ajax.request同步请求
导读: ajax分为2种,一种是同步,一种是异步同步:代码执行完了之后才执行后面的代码 异步:代码刚执行,后面的代码就马上接着执行了,不管前面的代码是否执行完异步的情况下,要获得返回信息,就需要在异步 ...
- Detecting an Ajax request in PHP
1:index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
随机推荐
- nginx配置aliyun https
server { listen 443; server_name www.goforit.com goforit.com; ssl on; ssl_certificate cert/goforit.p ...
- 关于memset赋最值
出处[辗转山河弋流歌 by 空灰冰魂] blog.csdn.net/vmurder/article/details/46537613 memset(a, 0x3f, sizeof(a)) //int, ...
- thymeleaf 教程
html页面 添加 <html xmlns:th="http://www.thymeleaf.org" > html原有标签都可以用thymeleaf标签替换 1.t ...
- awk技巧
1通过awk脚本执行awk程序:awk-f program_file_name input_files #!/bin/awk -f BEGIN { print "What is your n ...
- HDU 5303 Delicious Apples(贪心 + 背包 2015多校啊)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5303 Problem Description There are n apple trees plan ...
- 使用iVMS-4200 存储录像数据时的设置
1.安装软件时,选择:存储服务器 2.对存储服务器进行配置,具体配置见 配置手册.
- C/C++(C++类型增强)
C++类型增强 类型检查更严格 把一个const类型的指针赋给非const类型的指针.c语言中可以通的过,但是在c++中则编不过去 const int a = 10; a = 100;//const修 ...
- jq PC做滚动效果经常用到的各类参数【可视区判断】
获取 浏览器显示区域 (可视区域)的高度 : $(window).height(); 获取浏览器显示区域(可视区域)的宽度 : $(window).width(); 获取页面的文档高度: $( ...
- Centos/RHEL :How to add,delete and display LVM tags
1. 什么是LVM标签? 在你想开机启动时让逻辑卷被激活可用时,添加lvm标签是一个不错的选择.lvm标签允许那些被预先标记的实现这样的效果. 2. 配置文件 配置文件/etc/lvm/lvm.con ...
- Yeslab 华为安全HCIE-第五门-防火墙攻击防范技术
Yeslab 华为安全HCIE-第五门-防火墙攻击防范技术 课程目录 Yeslab华为安全HCIE-第五门-防火墙攻击防范技术(8篇)\1_单包攻击防范.aviYeslab华为安全HCIE-第五门-防 ...