I am trying to test my async
action and I get this error:
store.dispatch cannot read property 'then' of undefined
I tried to use the then
on the actionTypes
(I am sorry, that is an actionCreator
but I imported it as actionType
), but it goes from undefined
to:
TypeError: actionTypes.fetchGitHubDataAsync(...).then is not a function.
it('Dispatches BOOKS_SUCCESS after fetching books', () => {
// Response body sample
const mockData = [
{
"name": "javascript",
"display_name": "JavaScript",
"short_description": "JavaScript (JS) is a lightweight interpreted programming language with first-class functions.",
"description": "JavaScript (JS) is a lightweight interpreted or JIT-compiled programming language with first-class functions. While it is most well-known as the scripting language for Web pages, many non-browser environments also use it, such as Node.js, Apache CouchDB and Adobe Acrobat. JavaScript is a prototype-based, multi-paradigm, dynamic language, supporting object-oriented, imperative, and declarative (e.g. functional programming) styles.",
"created_by": "Brendan Eich",
"released": "December 4, 1995",
"created_at": "2016-11-28T18:41:00Z",
"updated_at": "2019-11-06T15:05:24Z",
"featured": true,
"curated": true,
"score": 7954.724
}
]
fetchMock.getOnce('https://api.github.com/search/topics?q=javascript',
{ body: { results: mockData }})
const expectedActions = [
{ type: actionTypes.FETCH_GITHUB_DATA},
]
store.dispatch(actionTypes.fetchGitHubDataAsync())
.then(() => {
expect(store.getActions()).toEqual(expectedActions)
})
})
actions js file
export const fetchGitHubDataAsync = () => {
return dispatch => {
fetch('https://api.github.com/search/topics?q=javascript', {
headers: {
'Accept': 'application/vnd.github.mercy-preview+json'
}
})
.then(res => res.json())
.then(json => {console.log('json', json.items.slice(0, 5));
return dispatch({type: 'FETCH_GITHUB_DATA', payload: json.items.slice(0, 5)})});
}
}
Here is an unit test working example without using third-party mock library.
action.js
:
export const fetchGitHubDataAsync = () => {
return dispatch => {
return fetch('https://api.github.com/search/topics?q=javascript', {
headers: {
Accept: 'application/vnd.github.mercy-preview+json'
}
})
.then(res => res.json())
.then(json => {
console.log('json', json.items.slice(0, 5));
return dispatch({ type: 'FETCH_GITHUB_DATA', payload: json.items.slice(0, 5) });
});
};
};
action.spec.js
:
import * as actionTypes from './action';
import createMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
const mws = [thunk];
const mockStore = createMockStore(mws);
const store = mockStore({});
describe('fetchGitHubDataAsync', () => {
it('Dispatches BOOKS_SUCCESS after fetching books', () => {
expect.assertions(2);
const mJson = { items: [1, 2, 3, 4, 5, 6] };
const mResponse = { json: jest.fn().mockResolvedValueOnce(mJson) };
global.fetch = jest.fn().mockResolvedValueOnce(mResponse);
const expectedActions = [{ type: 'FETCH_GITHUB_DATA', payload: [1, 2, 3, 4, 5] }];
return store.dispatch(actionTypes.fetchGitHubDataAsync()).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(global.fetch).toBeCalledWith('https://api.github.com/search/topics?q=javascript', {
headers: {
Accept: 'application/vnd.github.mercy-preview+json'
}
});
});
});
});
Unit test result with 100% coverage:
PASS src/stackoverflow/58803026/action.spec.js
fetchGitHubDataAsync
✓ Dispatches BOOKS_SUCCESS after fetching books (16ms)
console.log src/stackoverflow/58803026/action.js:239
json [ 1, 2, 3, 4, 5 ]
-----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
action.js | 100 | 100 | 100 | 100 | |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.329s, estimated 15s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58803026