React Redux 连接组件与异步动作测试
React Redux connected component with async action testing
我在 React-Redux 连接组件测试中遇到了问题。我想用异步操作测试这个组件,但在控制台中我总是收到错误...我使用 React-testing-library with jest 进行测试(不是酶)。
有控制台错误
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: [Function anonymous]
Received: [Function anonymous]
Number of calls: 1
45 | it('should dispatch an action on page first render', () => {
46 | expect(store.dispatch).toHaveBeenCalledTimes(1);
> 47 | expect(store.dispatch).toHaveBeenCalledWith(fetchTop10());
| ^
48 | });
49 | });
50 |<br /><br />
存在连通分量“CardList.js”
import React, { Fragment, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
// Redux
import { connect } from 'react-redux';
// Actions
import { fetchTop10 } from '../../actions/fetchTitles'; // async api call with data response
// Utils
import CardItem from './CardItem';
const CardList = ({ fetchTop10, top10 }) => {
useEffect(() => {
(async () => {
await fetchTop10();
})();
}, [fetchTop10]);
const renderCards = () => {
if (top10.length === 0) { // This is for sceletion insted of spinner
return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((el) => {
return <CardItem key={el} />;
});
}
return top10.map((title) => { // Actual data from action API call
return <CardItem key={title.id} title={title} />;
});
};
return (
<Fragment>
<section id="section-top" className="section-top">
<h3 className="section-top__heading">Week Bestlers</h3>
<div className="top-cards">{renderCards()}</div>
<Link to="/titles" className="section-top__btn btn-link">
view more →
</Link>
</section>
</Fragment>
);
};
CardList.propTypes = {
fetchTop10: PropTypes.func.isRequired,
top10: PropTypes.array.isRequired,
};
const mapStateToProps = (state) => {
return { top10: state.top10 };
};
export default connect(mapStateToProps, { fetchTop10 })(CardList);<br /><br />
测试“CardList.test.js”
import { render, cleanup } from '@testing-library/react';
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/extend-expect';
import React from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom'; // All project components are in global Router
import thunk from 'redux-thunk';
import configureStore from 'redux-mock-store'; // for provider store
// Component
import CardList from '../CardList';
// Objects
import { fakeTitle, fakeTitle2 } from '../../utils/UserTitleObjects'; // Just objects with data
import history from '../../../history';
import { fetchTop10 } from '../../../actions/fetchTitles'; // Action with API call
const mockStore = configureStore([thunk]);
describe('My Connected React-Redux Component', () => {
let store, component;
beforeEach(() => {
store = mockStore({
top10: [],
});
store.dispatch = jest.fn();
component = render(
<Provider store={store}>
<Router history={history}>
<CardList />
</Router>
</Provider>
);
});
afterEach(cleanup);
it('should render with given state from Redux store', () => {
expect(component.baseElement.querySelectorAll('.sceletion').length).toBe(
60
);
});
it('should dispatch an action on page first render', () => {
expect(store.dispatch).toHaveBeenCalledTimes(1); // this is good <--
expect(store.dispatch).toHaveBeenCalledWith(fetchTop10()); // Here starts a problem
});
});
在这种情况下,您必须模拟您的操作,否则,您的操作将 return 另一个很难断言的函数。
我建议像这样简单地模拟您的操作模块:
CardList.test.js
// ...
const mockStore = configureStore([thunk]);
jest.mock("../../../actions/fetchTitles", () => ({
__esModule: true,
fetchTop10: jest.fn(),
}));
// ...
我在 React-Redux 连接组件测试中遇到了问题。我想用异步操作测试这个组件,但在控制台中我总是收到错误...我使用 React-testing-library with jest 进行测试(不是酶)。
有控制台错误
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: [Function anonymous]
Received: [Function anonymous]
Number of calls: 1
45 | it('should dispatch an action on page first render', () => {
46 | expect(store.dispatch).toHaveBeenCalledTimes(1);
> 47 | expect(store.dispatch).toHaveBeenCalledWith(fetchTop10());
| ^
48 | });
49 | });
50 |<br /><br />
存在连通分量“CardList.js”
import React, { Fragment, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
// Redux
import { connect } from 'react-redux';
// Actions
import { fetchTop10 } from '../../actions/fetchTitles'; // async api call with data response
// Utils
import CardItem from './CardItem';
const CardList = ({ fetchTop10, top10 }) => {
useEffect(() => {
(async () => {
await fetchTop10();
})();
}, [fetchTop10]);
const renderCards = () => {
if (top10.length === 0) { // This is for sceletion insted of spinner
return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((el) => {
return <CardItem key={el} />;
});
}
return top10.map((title) => { // Actual data from action API call
return <CardItem key={title.id} title={title} />;
});
};
return (
<Fragment>
<section id="section-top" className="section-top">
<h3 className="section-top__heading">Week Bestlers</h3>
<div className="top-cards">{renderCards()}</div>
<Link to="/titles" className="section-top__btn btn-link">
view more →
</Link>
</section>
</Fragment>
);
};
CardList.propTypes = {
fetchTop10: PropTypes.func.isRequired,
top10: PropTypes.array.isRequired,
};
const mapStateToProps = (state) => {
return { top10: state.top10 };
};
export default connect(mapStateToProps, { fetchTop10 })(CardList);<br /><br />
测试“CardList.test.js”
import { render, cleanup } from '@testing-library/react';
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/extend-expect';
import React from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom'; // All project components are in global Router
import thunk from 'redux-thunk';
import configureStore from 'redux-mock-store'; // for provider store
// Component
import CardList from '../CardList';
// Objects
import { fakeTitle, fakeTitle2 } from '../../utils/UserTitleObjects'; // Just objects with data
import history from '../../../history';
import { fetchTop10 } from '../../../actions/fetchTitles'; // Action with API call
const mockStore = configureStore([thunk]);
describe('My Connected React-Redux Component', () => {
let store, component;
beforeEach(() => {
store = mockStore({
top10: [],
});
store.dispatch = jest.fn();
component = render(
<Provider store={store}>
<Router history={history}>
<CardList />
</Router>
</Provider>
);
});
afterEach(cleanup);
it('should render with given state from Redux store', () => {
expect(component.baseElement.querySelectorAll('.sceletion').length).toBe(
60
);
});
it('should dispatch an action on page first render', () => {
expect(store.dispatch).toHaveBeenCalledTimes(1); // this is good <--
expect(store.dispatch).toHaveBeenCalledWith(fetchTop10()); // Here starts a problem
});
});
在这种情况下,您必须模拟您的操作,否则,您的操作将 return 另一个很难断言的函数。
我建议像这样简单地模拟您的操作模块:
CardList.test.js
// ...
const mockStore = configureStore([thunk]);
jest.mock("../../../actions/fetchTitles", () => ({
__esModule: true,
fetchTop10: jest.fn(),
}));
// ...