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的更多相关文章

  1. Extjs4.0以上版本 Ext.Ajax.request请求的返回问题

    Ext.Ajax.request({ url: posturl, method: 'POST', params: { ClassName: 'XXXX', FuncName: 'XXXX', para ...

  2. [转] form.getForm().submit的用法及Ext.Ajax.request的小小区别

    原文地址:http://blog.csdn.net/hongleidy5000/article/details/7329325 if (!formDetail.getForm().isValid()) ...

  3. (ExtJs 3.4)Ext.Ajax.request的同步请求实现

    ext3.0之前都是这样来提交:var responsea = Ext.lib.Ajax.getConnectionObject().conn;responsea.open("POST&qu ...

  4. Extjs-Ext.Ajax.request设置超时

    ExtJs的Ajax提交主要是:Ext.Ajax.request或form1.getForm().submit,超时时间默认是30秒. 很多时候,后台处理比较多,往往需要超出30秒的限制.此时,可以通 ...

  5. EXTJS 资料 Ext.Ajax.request 获取返回数据

    下面是一个登陆页面调用的EXTJS login function,通过 url: '/UI/HttpHandlerData/Login/Login.ashx',获取返回登陆账户和密码! Ext.onR ...

  6. Ext.Ajax.request()方法和FormPanel.getForm().submit()方法,都返回success()方法的差异

    我还是不发表到博客园首页吧,要不然还是要被取消,>_< 还是言归正传吧,关于Ext.Ajax.request()方法和FormPanel.getForm().submit()方法返回suc ...

  7. 【转】Ext.ajax.request 中的success和failure

    原文链接:Ext.ajax.request 中的success和failure Ajax request对象的success事件表示request过程中没有发生错误,和自己的业务逻辑无关, 如果访问不 ...

  8. Ext.Ajax.request同步请求

    导读: ajax分为2种,一种是同步,一种是异步同步:代码执行完了之后才执行后面的代码 异步:代码刚执行,后面的代码就马上接着执行了,不管前面的代码是否执行完异步的情况下,要获得返回信息,就需要在异步 ...

  9. Detecting an Ajax request in PHP

    1:index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

随机推荐

  1. struts2登录后返回登录前的页面

    在Action中添加 String getUrl() { return ServletActionContext.getRequest().getHeader("referer") ...

  2. ArcGIS api for javascript——地图配置-

    描述 本例展示了如果删除缩放等级滑动器的刻度线.通过设置esriConfig里的sliderLabel为null来实现: esriConfig.defaults.map.sliderLabel = n ...

  3. 进程:linux用户态-内核态

    用户态:Ring3运行于用户态的代码则要受到处理器的诸多检查,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中I/O许可位图(I/O Permi ...

  4. C++语言笔记系列之十——静态成员

    1.静态成员 (1)由keywordstatic修饰 静态变量定义语句在编译阶段就运行,运行过程中不再运行. (2)分类:静态数据成员.静态成员函数. (3)静态成员时类的全部对象共享的成员,而不是某 ...

  5. PostgreSQL数据库创建/删除

    方法1 - 系统命令 sudo su - postgres #切换到postgres用户(系统用户) createdb weichen #创建数据库 psql #直接訪问数据库(默认进入本地postg ...

  6. 封装html代码块到js函数中

    有时候想把公共的html封装起来,怎么处理呢? 好多页面都用到,不可能每个页面都写,这样就会有冗余,并且不好统一处理. 那就用js来重构html吧. 代码案例如下: <footer class= ...

  7. Android - TextureView, SurfaceView和GLSurfaceView 以及 SurfaceTexture

    这几个概念比较绕, 又比较相近. 初看比较糊涂, 把握关键点就好. 关键字 View SurfaceViewGLSurfaceViewTextureView这三个后缀都是View, 所以这三个东西都是 ...

  8. Xml、Json序列化

    Xml序列化: public class XmlHelper { private static string XmlPath = Path.Combine(AppDomain.CurrentDomai ...

  9. 使用Spring Boot Actuator、Jolokia和Grafana实现准实时监控--转

    原文地址:http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247483789&idx=1&sn=ae11f04780 ...

  10. powerdesigner导出sql

    http://jingyan.baidu.com/article/7082dc1c48960ee40a89bd38.html 生成注释 http://wangjingyi.iteye.com/blog ...