I am doing Unit tests with jest and enzyme. I have following connected component with hooks. I called redux actions to load data.
import React, {useEffect, useState, useCallBack} from "react"; import {connect} from "react-redux"; import CustomComponent from "../Folder"; import { loadData, createData, updateData } from "../../redux/actions"; const AccountComponent = (props) => { const total = 50; const [aIndex, setAIndex] = useState(1); const [arr, setArr] = useState(['ds,dsf']); //... some state variables here const getData = () => { props.loadData(aIndex, total, arr); } useEffect(() => { getData(); },[aIndex, total]) //some other useEffect and useCallback return( <React.Fragment> <CustomComponent {...someParam}/> <div> ... </div> </React.Fragment> ) } const mapStateToProps = (state) => { const { param1, param2, parma3 } = state.AccountData; return { param1, param2, parma3 } } export default connect(mapStateToProps, { loadData, createData, updateData })(AccountComponent) Here, like following I created some test case for above component.
import AccountComponent from "../"; import React from "react"; import renderer from "react-test-renderer" describe("AccountComponent component", () => { const loadData = jest.fn(); let wrapper; it("snapshot testing", () => { const tree = renderer.create(<AccountComponent loadData={loadData} />).toJSON(); expect(tree).toMatchSnapshot(); }) beforeEach(() => { wrapper = shallow(<AccountComponent loadData={loadData} />).instance(); }); it('should call loadData', () => { expect(wrapper.loadData).toHaveBeenCalled(); }); }) But, It doesn't pass and shows error.
Error for snapshot testing:
invariant violation element type is invalid: expected string or a class/function
Error for method call testing:
Cannot read property 'loadData' of undefined.
Enzyme Internal error: Enzyme expects and adapter to be configured, but found none. ...
Not sure what the issue as I am not good in unit testing.
I am using react-redux 7.
Any help would be greatly appreciated.
Edit:
I also tried with provider like following. But, didn't help.
import { Provider } from "react-redux"; import {createStore} from "redux"; import reducer from "../../reducers"; const store = createStore(reducer); it("snapshot testing", () => { const tree = renderer.create(<Provider store={store}><AccountComponent loadData={loadData} /></Provider>).toJSON(); expect(tree).toMatchSnapshot(); }) beforeEach(() => { wrapper = shallow(<Provider store={store}><AccountComponent loadData={loadData} /></Provider>).instance(); });
loadDatawas called or not. You should test if data is visible at screen to end user or not (without worrying how it is loaded or which function is called to load it). And, it seems like you are testing a component connected with Redux store, but you provided it no Store when testing it. See redux.js.org/recipes/writing-testsactionsfile content forloadDataand as mentioned by Ajeet you need to provideproviderwith store as you component is connected toredux-storeAccountComponentso that component does not have a proploadData. That comes from Redux. @AjeetShah is correct that you need to load it inside a<Provider>. You could potentially export the unconnected version of the component to test and pass yourloadDatafunction as a prop which should work, but that test is not as informative.