admin管理员组文章数量:1194126
I am creating a middleware for making ajax requests using async actions. The middleware intercepts original action, performs ajax request, and re-dispatch
es the original action along with the response from the url
.
So, my Component would merely dispatch
an action like this
onClick() {
dispatch(ActionCreator.fetchUser());
}
Rest will be taken care by the middleware as shown here.
My question is, what should I do for unit testing? Should I mock the onClick
itself? or I should write a mocked middleware and forward the actions with the mocked response?
I am not sure which approach should I take. I tried several stuff, but none of what I tried made sense to me.
Any pointers?
I am creating a middleware for making ajax requests using async actions. The middleware intercepts original action, performs ajax request, and re-dispatch
es the original action along with the response from the url
.
So, my Component would merely dispatch
an action like this
onClick() {
dispatch(ActionCreator.fetchUser());
}
Rest will be taken care by the middleware as shown here.
My question is, what should I do for unit testing? Should I mock the onClick
itself? or I should write a mocked middleware and forward the actions with the mocked response?
I am not sure which approach should I take. I tried several stuff, but none of what I tried made sense to me.
Any pointers?
Share Improve this question asked Oct 8, 2015 at 9:26 SalmanSalman 9,4476 gold badges41 silver badges74 bronze badges2 Answers
Reset to default 25Note: answer below is slightly outdated.
A much simpler updated approach is described here.
You can still do it the other way too, though.
We now have a section on testing async action creators in the official docs.
For async action creators using Redux Thunk or other middleware, it’s best to completely mock the Redux store for tests. You can still use applyMiddleware()
with a mock store, as shown below. You can also use nock to mock the HTTP requests.
function fetchTodosRequest() {
return {
type: ADD_TODOS_REQUEST
};
}
function fetchTodosSuccess(body) {
return {
type: ADD_TODOS_SUCCESS,
body
};
}
function fetchTodosFailure(ex) {
return {
type: ADD_TODOS_FAILURE,
ex
};
}
export function fetchTodos(data) {
return dispatch => {
dispatch(fetchTodosRequest());
return fetch('http://example.com/todos')
.then(res => res.json())
.then(json => dispatch(addTodosSuccess(json.body)))
.catch(ex => dispatch(addTodosFailure(ex)));
};
}
can be tested like:
import expect from 'expect';
import { applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import * as actions from '../../actions/counter';
import * as types from '../../constants/ActionTypes';
import nock from 'nock';
const middlewares = [thunk];
/**
* Creates a mock of Redux store with middleware.
*/
function mockStore(getState, expectedActions, onLastAction) {
if (!Array.isArray(expectedActions)) {
throw new Error('expectedActions should be an array of expected actions.');
}
if (typeof onLastAction !== 'undefined' && typeof onLastAction !== 'function') {
throw new Error('onLastAction should either be undefined or function.');
}
function mockStoreWithoutMiddleware() {
return {
getState() {
return typeof getState === 'function' ?
getState() :
getState;
},
dispatch(action) {
const expectedAction = expectedActions.shift();
expect(action).toEqual(expectedAction);
if (onLastAction && !expectedActions.length) {
onLastAction();
}
return action;
}
}
}
const mockStoreWithMiddleware = applyMiddleware(
...middlewares
)(mockStoreWithoutMiddleware);
return mockStoreWithMiddleware();
}
describe('async actions', () => {
afterEach(() => {
nock.cleanAll();
});
it('creates FETCH_TODO_SUCCESS when fetching todos has been done', (done) => {
nock('http://example.com/')
.get('/todos')
.reply(200, { todos: ['do something'] });
const expectedActions = [
{ type: types.FETCH_TODO_REQUEST },
{ type: types.FETCH_TODO_SUCCESS, body: { todos: ['do something'] } }
]
const store = mockStore({ todos: [] }, expectedActions, done);
store.dispatch(actions.fetchTodos());
});
});
Turns out, I don't need to mock any store methods or anything. Its as simple as mocking the ajax request. I am using superagent
, so I did it something like this
const mockResponse = {
body: {
data: 'something'
}
};
spyOn(superagent.Request.prototype, 'end').and.callFake((cb) => {
cb(null, mockResponse); // callback with mocked response
});
// and expect it to be called
expect(superagent.Request.prototype.end).toHaveBeenCalled();
本文标签: javascriptHow to unit test async Redux actions to mock ajax responseStack Overflow
版权声明:本文标题:javascript - How to unit test async Redux actions to mock ajax response - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738498977a2090155.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论