I am new to react native. I have implemented functionality and snapshot unit testing but not sure how to write functional and API level unit test cases. I am using enzyme and jest. also I have used redux for state management.
following is my few files .
App.js
/* eslint-disable no-unused-vars */
/* eslint-disable no-use-before-define */
/* eslint-disable class-methods-use-this */
import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import axios from 'axios';
import axiosMiddleware from 'redux-axios-middleware';
import * as myConstant from './src/common/constants';
import reducer from './src/reducer/reducer';
import Navigation from './src/common/navigator';
const client = axios.create({
baseURL: myConstant.API,
responseType: 'json',
timeout: 25000,
});
const store = createStore(reducer, applyMiddleware(axiosMiddleware(client)));
export default class App extends Component {
render() {
return (
<Provider store={store}>
<View style={styles.container}>
<Navigation />
</View>
</Provider>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
marginTop: 50,
},
});
home.js
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable no-unused-vars */
import React, { Component } from 'react';
import { ActivityIndicator } from 'react-native-paper';
import {
View, Text, FlatList, TouchableOpacity,
} from 'react-native';
import { connect } from 'react-redux';
import { Ionicons } from '@expo/vector-icons';
import styles from './style';
import { listRepos } from '../../reducer/reducer';
import ErrorAlert from '../../common/errorAlertComponent/errorAlert';
class Home extends Component {
componentDidMount() {
this.props.listRepos();
}
FlatListItemSeparator = () => (
<View style={styles.flatListItemSeparator} />
)
renderItem = ({ item }) => (
<View style={styles.listRowContainer}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('ThumbnailViewScreen', {
albumID: item.id,
})} style={styles.listRow}>
<View style={styles.listTextNavVIew}>
<Text style={styles.albumTitle}> {item.title} </Text>
<Ionicons name='md-arrow-dropright' style={styles.detailArrow} />
</View>
</TouchableOpacity>
</View>
);
render() {
const { error, loading, albums } = this.props;
if (error) {
return <ErrorAlert />;
}
if (loading) {
return (
<View style={{ flex: 1, paddingTop: 30 }}>
<ActivityIndicator animating={true} size='large' />
</View>
);
}
return (
<View style={styles.MainContainer} >
<FlatList
styles={styles.container}
data={albums}
renderItem={this.renderItem}
ItemSeparatorComponent={this.FlatListItemSeparator}
/>
</View>
);
}
}
const mapStateToProps = (state) => {
const storedRepositories = state.albums.map((repo) => ({ key: repo.id.toString(), ...repo }));
return {
albums: storedRepositories,
loading: state.loading,
error: state.error,
};
};
const mapDispatchToProps = {
listRepos,
};
export default connect(mapStateToProps, mapDispatchToProps)(Home);
reducer.js
export const GET_ALBUM = 'album/LOAD';
export const GET_ALBUM_SUCCESS = 'album/LOAD_SUCCESS';
export const GET_ALBUM_FAIL = 'album/LOAD_FAIL';
const initialState = {
albums: [],
loading: false,
error: null,
};
export default function reducer(state = initialState, action) {
switch (action.type) {
case GET_ALBUM:
return { ...state, loading: true };
case GET_ALBUM_SUCCESS:
return { ...state, loading: false, albums: action.payload.data };
case GET_ALBUM_FAIL:
return {
...state,
loading: false,
error: 'Error while fetching albums',
};
default:
return state;
}
}
export function listRepos() {
return {
type: GET_ALBUM,
payload: {
request: {
url: 'photos/',
},
},
};
}
export function listThumb(albumId) {
return {
type: GET_ALBUM,
payload: {
request: {
url: `photos?albumId=${albumId}`,
},
},
};
}
Well for testing api first of you will need to use some function to fetch (fetch function) but that will have to be mocked as you don't want to make an actual request while testing.
// Mocking the global.fetch included in React Native
global.fetch = jest.fn();
// Helper to mock a success response (only once)
fetch.mockResponseSuccess = (body) => {
fetch.mockImplementationOnce (
() => Promise.resolve({json: () => Promise.resolve(JSON.parse(body))})
);
};
// Helper to mock a failure response (only once)
fetch.mockResponseFailure = (error) => {
fetch.mockImplementationOnce(
() => Promise.reject(error)
);
};
next you will need to use a mocked version of your redux store which you can do using redux-mock-store
// __mocks__/redux-mock-store.js
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
const middlewares = [ thunk ];
const mockStore = configureMockStore(middlewares);
export default mockStore;
after you finish setting up those now you can test your async actions. In this case you are testing for these:
it('should handle TEST_API_SUCCESS action', async () => { const response = '{"items": [{"id": 1}]}'; fetch.mockResponseSuccess(response); await store.dispatch(fetchData('/test', receiveTestData)); expect(store.getActions()).toMatchSnapshot(); });
all credits and more information you can find on: Callstack
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With