[Redux-Observable && Unit Testing] Mocking an ajax request when testing epics
2024-08-31 16:30:22
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
最新文章
- EasyUI需注意的问题01
- window.showModalDialog返回值和window.open返回值实例详解
- 2016年10月27日--css样式表
- [转]关于 initWithNibName 和 loadNibNamed 的区别和联系
- 实现C#给系统其他窗口输入的思路
- 设计模式 - 策略模式(Strategy Pattern) 具体解释
- keybd_event函数用法
- 大数据系列修炼-Scala课程09
- 简说Python生态系统的14年演变
- ios手机访问H5页面中$(document).on绑定无效问题
- centos6.5 python命令行模式左右建无法使用
- 使用idea+springboot+Mybatis搭建web项目
- Mybatis 使用了哪些设计模式?
- “数学口袋精灵”App的第三个Sprint计划----开发日记(第十一天12.17)
- Vue插件写、用详解(附demo)
- 用 CPI 火焰图分析 Linux 性能问题
- JAVA代码MD5加密方法
- TensorFlow随机值:tf.random_normal函数
- rap 部署
- JAVA-jar包下载地址
热门文章
- Win10+CUDA9.0+cuDNN7.2 下载 安装 配置
- 【Henu ACM Round#19 B】 Luxurious Houses
- gcc 生成动态链接库
- Codeforces Round #313 C. Gerald&;#39;s Hexagon(放三角形)
- UI_UISegmentedControl 控件
- Hadoop2.2集群安装配置-Spark集群安装部署
- java内部类的初始化
- .net 项目分层及规范
- Chromium Graphics : GPU Accelerated Compositing in Chrome
- js002---- 标准内置对象