javascript - React/Enzyme 组件函数不更新状态

标签 javascript reactjs tdd enzyme

我有一个可以在本地主机上运行的组件。如果您输入冠军的字母,onInputHandler(input) 会将组件的状态更改为有效冠军的名称。不幸的是,当我用 enzyme 进行测试时,组件的状态永远不会改变(保持默认状态)。我很乐意提供任何建议。当我用数组设置 this.statechampionsList 时,结果是相同的。通常,该数组在 componentDidMount() 之后用 getChampionsList() 填充。

        export class ChooseChampion extends React.Component {
    constructor() {
        super();
        this.state = {
            championSelected: "Choose champion",
            championsList: []
        };

        this.onInputHandler = this.onInputHandler.bind(this);
        this.getFilteredChampion = this.getFilteredChampion.bind(this);
    }

    componentDidMount() {
        this.getChampionsList();
    }

    getChampionsList = () => {
        fetch('/champions-list')
            .then(res => res.json())
            .then(champions => this.setState({ championsList: champions }))
    }

    onInputHandler(event) {
        if (event.target.value === "") {
            this.setState({
                championSelected: "Choose champion"
            });
        } else {
            const input = event.currentTarget.value;
            const filteredChampion = this.getFilteredChampion(input)
            this.setState({
                championSelected: filteredChampion
            });
        }
    }

    getFilteredChampion(input) {
        let oneFilteredChampion = this.state.championsList.find(champion => champion.toLowerCase().includes(input.toLowerCase()))
        if (oneFilteredChampion) {
            return oneFilteredChampion;
        } else {
            return "Wrong name!"
        }
    }

    render() {
        return (
            <div className="choose-champion-container">

                <div className="role-and-caption inactive">
                    <img className="role-icon" src={require(`../assets/images/${this.props.lane}_icon.png`)} alt={this.props.lane} />
                    <span className="role-caption">{this.props.lane}</span>
                </div>

                <div className="champion-avatar-and-caption">
                    <ChampionAvatar currentChampion={this.state.championSelected} championsList={this.state.championsList} />
                    <ChampionCaption currentChampion={this.state.championSelected} championsList={this.state.championsList} />
                </div>

                <div className="search-container">
                    <button type="submit" className="search-button"><img src={SearchIcon} className="search-icon" alt="Search" /></button>
                    <input type="text" placeholder="Find champion..." name="search" onInput={this.onInputHandler} />
                </div>
            </div>
        )
    };
}

这是我的测试声明:

const lanes = ["Top", "Jungle", "Middle", "Bottom", "Support"]
const app = <ChooseChampion lane={lanes[Math.floor(Math.random() * (5))]} />;

it('Should change the state after change the input value', () => {
  const newValue = 'Ahri';
  const wrapper = mount(app);
  const input = wrapper.find('input');

  input.value = newValue;

  wrapper.update();
  expect(input.value).toEqual(newValue);
  expect(wrapper.state('championSelected')).toEqual(newValue);
});

最佳答案

尝试更换

input.value = newValue;

input.simulate('change', {target: {value: newValue}});

input.simulate('input', {target: {value: newValue}});

要实际触发事件(onChangeonInput),您需要模拟 DOM 事件。仅更改输入中的值不会触发 React 监听器。

另一件事是您在 componentDidMount 中进行提取。这是一个异步调用。 mount 之后,冠军列表将不会被填充。有几种方法可以等待它。您可以使用wait-for-expect或者自己写一个类似的函数。因此,最终测试应该类似于:

it('Should change the state after change the input value', () => {
  const newValue = 'Ahri';
  const wrapper = mount(app);

  await waitForExpect(() => {
    expect(wrapper.state('championsList')).to.be.not.empty;
  });

  const input = wrapper.find('input');

  input.simulate('change', {target: {value: newValue}});

  wrapper.update();
  expect(input.value).toEqual(newValue);
  expect(wrapper.state('championSelected')).toEqual(newValue);
});

注意:您可能更喜欢使用 nock 这样的工具模拟后端而不是在测试中调用实际端点。

关于javascript - React/Enzyme 组件函数不更新状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61487884/

相关文章:

javascript - 播放音频文件返回 "Uncaught (in promise)"但在控制台中有效

javascript - 出现覆盖时防止背景滚动

Javascript |执行 for 循环的其他方法可能会在成功后中断?

reactjs - 根据值响应子元素调用父元素

javascript - 在React功能组件中,在鼠标悬停时加载react-bootstrap的下拉数据,而不是在鼠标单击时加载?

java - 在步骤中访问 JBehave Examples 表数据

javascript - 如何使用JavaScript检测冷门浏览器(baidu)?

reactjs - React/JSX 如何指定内置 HTML 类型作为变量

TDD 和模拟

unit-testing - 管理单元测试的维护负担