代码之家  ›  专栏  ›  技术社区  ›  Faraz

测试通过子组件更新的父组件中的状态

  •  0
  • Faraz  · 技术社区  · 7 年前

    onFormSubmit onFormSubmit 调用子组件内的函数将值传递回父组件。那么这个 函数执行某种检查,并在此基础上更新父组件中的状态。

    我想模拟/取消这个ajax/api调用。我怎样才能做到这一点?或者,我该如何编写代码,使这个场景是可测试的。

    我的父组件如下所示:

    class App extends React.Component {
    
    state: { message: "" }; //I want to test the state of message
    
    onFormSubmit = async (form) => {
        if (form.primaryEmail !== "") {
            const response = await axios.post("api/", form);
            this.setState(
                {
                    message: (response.status === 200) ? "Your email has been updated." : ""
                });
        } else {
            this.setState({ message: "No Update" });
        }
    }
    
    render() {
        return (
            <div>
                <Child onSubmit={this.onFormSubmit} />
                <h4>{this.state.message}</h4>
            </div>
        );
    }
    }
    

    我的子组件如下所示:

    class Child extends React.Component {
    state = {
        primaryEmail: "",
    };
    
    onPrimaryEmailChange = e => {
        this.setState({ primaryEmail: e.target.value });
    }
    
    onFormSubmit = e => {
        e.preventDefault();
        this.props.onSubmit(this.state); //passing the value back to parent component
    }
    
    render() {
        return (
            <form onSubmit={this.onFormSubmit}>
                <h3>Email Address</h3>
                <div>
                    <input type="email" value={this.state.primaryEmail} onChange={this.onPrimaryEmailChange} />
                </div>
                <div>
                    <button type="submit">Submit</button>
                </div>
            </form >
        );
    }
    }
    

    test("When valid form is submitted, it should show a success message", () => {
    const wrapper = mount(<App />);
    wrapper.find("input").at(0).simulate("change", {
      target: {
        value: "a@b.c",
      }
    });
    wrapper.find('form').simulate('submit');
    expect(wrapper.state('message')).toEqual('Your email has been updated.');
    });
    

    我得到这个错误:

    期望值等于:

    收到:

    ""

    1 回复  |  直到 6 年前
        1
  •  3
  •   rickdenhaan    7 年前

    免责声明: 我从内存中直接将其写入StackOverflow应答字段,因此它可能不是100%准确。

    create-react-app __mocks__ 项目根目录中的文件夹。

    __mocks__/axios.js :

    export default {
        // since you are only testing "axios.post()", I'm only mocking "post"
        post: jest.fn()
    }
    

    然后在父组件的测试中,可以为 post 返回200响应的函数(您正在测试的就是这种情况)。

    __tests__/App.test.jsx :

    // in Jest context, this should load from __mocks__/axios.js
    import axios from "axios";
    
    test("When valid form is submitted, it should show a success message", () => {
        // Axios itself returns a Promise, so the mock should as well
        axios.post.mockImplementationOnce(
            (url, formData) => Promise.resolve({
                status: 200
            })
        );
    
        const wrapper = mount(<App />);
    
        // Optionally, test the default state to be an empty string
        expect(wrapper.state()).toHaveProperty("message");
        expect(wrapper.state().message).toBe("");
    
        wrapper.find("input").at(0).simulate("change", {
            target: {
                value: "a@b.c",
            }
        });
    
        wrapper.find("form").simulate("submit");
    
        // Optionally, test if Axios was called
        expect(axios.post).toHaveBeenCalled();
    
        // More optionally, test if it was called with the correct email address
        expect(axios.post).toHaveBeenCalledWith(
            expect.any(),
            expect.objectContaining({ primaryEmail: "a@b.c" })
        );
    
        // Note that even though Axios may have been called, the asynchronous
        // Promise may not have completed yet which means the state will not
        // have been updated yet. To be safe, let's use setImmediate(), which
        // should wait for any pending Promises to complete first
        setImmediate(async () => {
            // Now we can test that the state has changed
            expect(wrapper.state().message).toBe("Your email has been updated.");
        });
    });
    
    推荐文章