模拟由 Redux 提供程序组件包含的 React 组件函数



这是我的情况: 我正在尝试对一个 React 组件 (TodoList( 进行单元测试,该组件在 Render 方法上除了映射项目并显示它们之外什么都不做。 它通过使用MapStateToProps从Redux存储中获取项目(TodoItem(。

这是 TodoList 组件的 JavaScript 代码:

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 委托方法。

我尝试使用Jest提供的模拟函数,结合酶。但是,由于TodoList从Redux获取数据,因此我必须使用Provider组件包围我的Enzyme mount((调用并模拟存储。

这是我的测试代码:

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 组件,因为提供程序包装器......

有什么线索吗?

通过大量的试验和错误修复了它。 我能够通过酶查找功能访问TodoList,该功能显然也适用于ComponentNames(而不仅仅是普通的HTML选择器(。

第二个技巧是在TodoList组件上调用forceUpdate((和在父包装器上调用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');
});

最新更新