Вот моя ситуация: Я пытаюсь провести модульное тестирование компонента React (TodoList), который ничего не делает с методом Render, кроме сопоставления элементов и их отображения. Он получает элементы (TodoItem) из магазина Redux с помощью MapStateToProps.
Это код javascript для компонента TodoList:
class TodoList extends React.Component {
onRemoveClick = (id) => {
diContainer.dataLayer.todo.remove(id);
}
render() {
const todos = this.props.todos;
if (!todos)
return null;
return (
todos.map(todo => (
<TodoItem key = {todo.id} todo = {todo} onRemove = {this.onRemoveClick} />
))
);
}
}
const mapStateToProps = (state) => ({
todos: state.todos
});
export default connect(mapStateToProps)(TodoList);
Сейчас я хочу проверить, что всякий раз, когда вызывается кнопка внутри TodoItem (дочерний объект), вызывается метод делегата onRemoveClick.
Я пробовал использовать функцию mocking, которую предоставляет Jest, вместе с Enzyme. Однако, поскольку TodoList получает свои данные из Redux, я должен окружить мой вызов Enzyme mount () компонентом Provider и имитировать хранилище.
Вот мой тестовый код:
import React from 'react';
import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import TodoList from '../../../../react/components/todo/TodoList';
describe('TodoList component', () => {
//global arrange
const storeState = {
todos: [
{
id: 'testId1',
title: 'testTitle1',
description: 'testDescription1'
},
{
id: 'testId2',
title: 'testTitle2',
description: 'testDescription2'
},
]
};
const mockStore = configureStore();
let store;
beforeEach(() => {
store = mockStore(storeState)
});
it('Removes a todo from the list if the remove button the todo was pressed', () => {
//arrange
//let mockFn = jest.fn();
//TodoList.prototype.onRemoveClick = mockFn; => tried, doesn't work...
const component = mount(
<Provider store = {store}>
<TodoList />
</Provider>
);
//component.instance() => tried working with this, but couldn't find it
//component.instance().children() => is not the TodoList
const items = component.find('.todoItem');
//act
const button = items.first().find('button');
button.simulate('click');
//assert
//Todo: check function spy here
});
});
Я прокомментировал некоторые вещи, которые пробовал. Но я не могу получить доступ к компоненту TodoList в моем тестовом коде из-за оболочки Provider ...
Какие-нибудь подсказки?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Исправлено через множество проб и ошибок. Мне удалось получить доступ к TodoList через функцию поиска ферментов, которая, по-видимому, также работает с ComponentNames (а не только с простыми селекторами HTML).
Второй трюк заключался в вызове forceUpdate () в компоненте TodoList И update () в родительской оболочке.
it('Removes a todo from the list if the remove button on the todo was pressed', () => {
//arrange
const component = mount(
<Provider store = {store}>
<TodoList />
</Provider>
);
const list = component.find('TodoList').instance();
let mockFn = jest.fn();
list.onRemoveClick = mockFn;
list.forceUpdate();
component.update();
//act
const items = component.find('.todoItem');
const button = items.first().find('button');
button.simulate('click');
//assert
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(1);
expect(mockFn).toHaveBeenCalledWith('testId1');
});