#javascript #reactjs #redux #jestjs #enzyme
#javascript #reactjs #redux #jestjs #фермент
Вопрос:
Я пытаюсь подсмотреть метод «getTableData» или любой другой метод компонента класса, используя jest «spyOn» или sinon «spy». Все время получать:
Cannot spy the getTableData property because it is not a function; undefined given instead
с помощью jest spyOn и
TypeError: Attempted to wrap undefined property getTableData as function
с помощью sinon spy.
Также компонент, метод которого я тестирую, обернут специальным компонентом, который использует redux connect. Затем я попытался экспортировать его без HOC, но тест по-прежнему не работает с той же ошибкой
Обратите внимание, что const spy = jest.spyOn(wrapper.instance(), "getTableData");
это нормально работает только с компонентом, экспортируемым без HOC!
Что я уже пробовал:
const spy = sinon.spy(MonthlyProjectPlan.prototype, 'getTableData');
//const spy = jest.spyOn(MonthlyProjectPlan.prototype, 'getTableData');
const wrapper = mount(
//<Provider store={store}>
<MonthlyProjectPlan {...propsPanel} />
//</Provider>
);
export class MonthlyProjectPlan extends React.Component {
groupBy = (list, keyGetter) => {
//some secret magic
};
getTableData = () => {
let result = [];
if (this.props.data) {
let groupedData = this.groupBy(this.props.data, item => item.commodity);
// magic
}
return result
};
getTableColumns = () => {
let tableData = this.getTableData();
let columns = [
{Header: 'Commodities', accessor: 'commodity', width: 300}
];
if (tableData.length > 0) {
let months = tableData[0].data.map(item => item.year_month_date);
let monthsColumns = months.map((item, key) => {
//magic
});
columns.push(...monthsColumns)
}
return columns
};
render() {
if (!this.props.data)
return (<LoadingBar/>);
if (this.props.data.length < 1)
return (<NoData/>);
return (
<div>
<ReactTable data={this.getTableData()}
className="monthly-pipeline__table"
columns={this.getTableColumns()}
defaultSorted={[{id: "commodity", desc: false}]}
showPageSizeOptions={false}
showPagination={false}
minRows={false}/>
<div className="monthly-pipeline-help">
<div className="monthly-pipeline-help__title">
Monthly Pipeline Shortfalls Percent
</div>
<table className="monthly-pipeline-help__table">
<tbody>
<tr>
<td style={{backgroundColor: colors.darkGreen}}>0% - 25%</td>
<td style={{backgroundColor: colors.yellow}}>26% - 50%</td>
<td style={{backgroundColor: colors.orange}}>51% - 75%</td>
<td style={{backgroundColor: colors.red}}>76% - 100%</td>
</tr>
</tbody>
</table>
</div>
</div>
)
}
}
export default Panel(MonthlyProjectPlan)
Приведенный ниже тест не работает
it("should render MonthlyProjectPlan Global component correctly", () => {
const spy = sinon.spy(MonthlyProjectPlan.prototype, 'getTableData');
//const spy = jest.spyOn(MonthlyProjectPlan.prototype, 'getTableData');
const wrapper = mount(
//<Provider store={store}>
<MonthlyProjectPlan {...propsPanel} />
//</Provider>
);
ошибки:
«Невозможно просмотреть свойство getTableData, потому что оно не является функцией; вместо этого задано неопределенное» с помощью jest spyOn
и
«Ошибка типа: попытка обернуть неопределенное свойство getTableData как функцию» с помощью sinon spy.
Это работает нормально, но только с компонентом, экспортируемым без HOC
it("should render MonthlyProjectPlan Global component correctly", () => {
const wrapper = mount(
//<Provider store={store}>
<MonthlyProjectPlan {...propsPanel} />
//</Provider>
);
// const spy = jest.spyOn(wrapper.instance(), "getTableData");
// wrapper.instance().forceUpdate();
// expect(spy).toHaveBeenCalled();
// expect(spy.mock.calls.length).toBe(5);
Ответ №1:
Вы определяете метод getTableData как свойство класса. Следовательно, метод не определен в прототипе. Вместо этого это свойство созданного вами экземпляра.
Это означает, что код (упрощенная версия предоставленного вами кода):
export class MonthlyProjectPlan {
getTableData = () => {
let result = [];
if (this.props.data) {
let groupedData = this.groupBy(this.props.data, item => item.commodity);
// magic
}
return result
};
render() {
}
}
такое же, как:
function MonthlyProjectPlan() {
this.getTableData = function() {
let result = [];
if (this.props.data) {
let groupedData = this.groupBy(this.props.data, item => item.commodity);
// magic
}
return result
};
}
MonthlyProjectPlan.prototype.render = function() {};
Обратите внимание, что метод getTableData не определен в прототипе класса MonthlyProjectPlan, а новый метод создается для каждого экземпляра создаваемого вами класса.
Из-за этого MonthlyProjectPlan.prototype.getTableData
оно не определено, и вы не можете его отслеживать.
Комментарии:
1. можете ли вы объяснить это, пожалуйста: «Вы определяете метод getTableData как свойство класса. Следовательно, метод не определен в прототипе. Вместо этого это свойство созданного вами экземпляра. » Почему это происходит и что я должен сделать, чтобы мой тест работал?
2. Я отредактировал свой ответ, чтобы подробнее объяснить, что я имел в виду. Надеюсь, это поможет!