Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/474.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何测试componentDidMount中设置React组件状态的异步调用_Javascript_Reactjs_Mocha.js_Chai_Enzyme - Fatal编程技术网

Javascript 如何测试componentDidMount中设置React组件状态的异步调用

Javascript 如何测试componentDidMount中设置React组件状态的异步调用,javascript,reactjs,mocha.js,chai,enzyme,Javascript,Reactjs,Mocha.js,Chai,Enzyme,测试componentDidMount中的异步调用设置React组件状态的最佳方法是什么?对于上下文,我用于测试的库有Mocha、Chai、Enzyme和Sinon 下面是一个示例代码: /* * assume a record looks like this: * { id: number, name: string, utility: number } */ // asyncComponent.js class AsyncComponent extends React.Compon

测试
componentDidMount
中的异步调用设置React组件状态的最佳方法是什么?
对于上下文,我用于测试的库有
Mocha
Chai
Enzyme
Sinon

下面是一个示例代码:

/* 
 * assume a record looks like this:
 * { id: number, name: string, utility: number }
 */

// asyncComponent.js
class AsyncComponent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            records: []
        };
    }

    componentDidMount() {
        // assume that I'm using a library like `superagent` to make ajax calls that returns Promises

        request.get('/some/url/that/returns/my/data').then((data) => {
            this.setState({
                records: data.records
            });
        });
    }

    render() {
        return (
            <div className="async_component">
                { this._renderList() }
            </div>
        );
    }

    _renderList() {
        return this.state.records.map((record) => {
            return (
                <div className="record">
                    <p>{ record.name }</p>
                    <p>{ record.utility }</p>
                </div>
            );
        });
    }
}


// asyncComponentTests.js
describe("Async Component Tests", () => {
    it("should render correctly after setState in componentDidMount executes", () => {
        // I'm thinking of using a library like `nock` to mock the http request

       nock("http://some.url.com")
           .get("/some/url/that/returns/my/data")
           .reply(200, {
               data: [
                   { id: 1, name: "willson", utility: 88 },
                   { id: 2, name: "jeffrey", utility: 102 }
               ]
           });

       const wrapper = mount(<AsyncComponent />);

       // NOW WHAT? This is where I'm stuck.
    });
});
/*
*假设记录如下所示:
*{id:number,name:string,utility:number}
*/
//asyncComponent.js
类AsyncComponent扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
记录:[]
};
}
componentDidMount(){
//假设我正在使用像‘superagent’这样的库来进行返回承诺的ajax调用
获取('/some/url/that/returns/my/data')。然后((data)=>{
这是我的国家({
记录:数据记录
});
});
}
render(){
返回(
{this.\u renderList()}
);
}
_renderList(){
返回此.state.records.map((记录)=>{
返回(
{record.name}

{record.utility}

); }); } } //asyncComponentTests.js 描述(“异步组件测试”,()=>{ 它(“应该在componentDidMount中的setState执行后正确呈现”,()=>{ //我正在考虑使用类似'nock'的库来模拟http请求 诺克(“http://some.url.com") .get(“/some/url/that/returns/my/data”) .答复(200{ 数据:[ {id:1,名称:“willson”,实用程序:88}, {id:2,名称:“jeffrey”,实用程序:102} ] }); const wrapper=mount(); //现在怎么办?这就是我被困的地方。 }); });
忽略理智的建议,重新思考结构,一种方法是:

  • 模拟请求(与sinon进行外汇交易),使其返回对某些记录的承诺
  • 使用酶的
    mount
    功能
  • 断言该州还没有您的记录
  • 让您的rest函数使用
    done
    回调
  • 稍等一下(使用
    setImmediate
    进行外汇兑换),这将确保您的承诺得到解决
  • 再次在已安装的组件上断言,这一次检查状态是否已设置
  • 调用已完成回调以通知测试已完成
因此,简言之:

// asyncComponentTests.js
describe("Async Component Tests", () => {
    it("should render correctly after setState in componentDidMount executes", (done) => {
        nock("http://some.url.com")
           .get("/some/url/that/returns/my/data")
           .reply(200, {
               data: [
                   { id: 1, name: "willson", utility: 88 },
                   { id: 2, name: "jeffrey", utility: 102 }
               ]
           });

        const wrapper = mount(<AsyncComponent />);

        // make sure state isn't there yet
        expect(wrapper.state).to.deep.equal({});

        // wait one tick for the promise to resolve
        setImmediate(() => {
            expect(wrapper.state).do.deep.equal({ .. the expected state });
            done();
        });
    });
});
//asyncComponentTests.js
描述(“异步组件测试”,()=>{
它(“应在componentDidMount中的setState执行后正确呈现”,(完成)=>{
诺克(“http://some.url.com")
.get(“/some/url/that/returns/my/data”)
.答复(200{
数据:[
{id:1,名称:“willson”,实用程序:88},
{id:2,名称:“jeffrey”,实用程序:102}
]
});
const wrapper=mount();
//确保州还没到
expect(wrapper.state).to.deep.equal({});
//等待承诺的解决
setImmediate(()=>{
expect(wrapper.state.do.deep.equal({..the expected state});
完成();
});
});
});
注:


我对nock没有任何线索,因此我在这里假设您的代码是正确的。实际上,这是一个常见的问题,由于承诺和
componentDidMount
,它显得更加复杂: 您正在尝试测试仅在另一个函数范围内定义的函数。i、 你应该把你的功能分开,分别测试

组件

class AsyncComponent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            records: []
        };
    }

    componentDidMount() {
        request.get('/some/url/that/returns/my/data')
            .then(this._populateState);
    }

    render() {
        return (
            <div className="async_component">
                { this._renderList() }
            </div>
        );
    }

    _populateState(data) {
        this.setState({
            records: data.records
        });
    }

    _renderList() {
        return this.state.records.map((record) => {
            return (
                <div className="record">
                    <p>{ record.name }</p>
                    <p>{ record.utility }</p>
                </div>
            );
        });
    }
}
// asyncComponentTests.js
describe("Async Component Tests", () => {
    describe("componentDidMount()", () => {
        it("should GET the user data on componentDidMount", () => {
            const data = {
                records: [
                    { id: 1, name: "willson", utility: 88 },
                    { id: 2, name: "jeffrey", utility: 102 }
                ]
            };
            const requestStub = sinon.stub(request, 'get').resolves(data);
            sinon.spy(AsyncComponent.prototype, "_populateState");
            mount(<AsyncComponent />);

            assert(requestStub.calledOnce);
            assert(AsyncComponent.prototype._populateState.calledWith(data));
        });
    });

    describe("_populateState()", () => {
        it("should populate the state with user data returned from the GET", () => {
            const data = [
                { id: 1, name: "willson", utility: 88 },
                { id: 2, name: "jeffrey", utility: 102 }
            ];

            const wrapper = shallow(<AsyncComponent />);
            wrapper._populateState(data);

            expect(wrapper.state).to.deep.equal(data);
        });
    });
});
类AsyncComponent扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
记录:[]
};
}
componentDidMount(){
get('/some/url/that/returns/my/data')
.然后(这一点);
}
render(){
返回(
{this.\u renderList()}
);
}
_填充测试(数据){
这是我的国家({
记录:数据记录
});
}
_renderList(){
返回此.state.records.map((记录)=>{
返回(
{record.name}

{record.utility}

); }); } }
单元测试

class AsyncComponent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            records: []
        };
    }

    componentDidMount() {
        request.get('/some/url/that/returns/my/data')
            .then(this._populateState);
    }

    render() {
        return (
            <div className="async_component">
                { this._renderList() }
            </div>
        );
    }

    _populateState(data) {
        this.setState({
            records: data.records
        });
    }

    _renderList() {
        return this.state.records.map((record) => {
            return (
                <div className="record">
                    <p>{ record.name }</p>
                    <p>{ record.utility }</p>
                </div>
            );
        });
    }
}
// asyncComponentTests.js
describe("Async Component Tests", () => {
    describe("componentDidMount()", () => {
        it("should GET the user data on componentDidMount", () => {
            const data = {
                records: [
                    { id: 1, name: "willson", utility: 88 },
                    { id: 2, name: "jeffrey", utility: 102 }
                ]
            };
            const requestStub = sinon.stub(request, 'get').resolves(data);
            sinon.spy(AsyncComponent.prototype, "_populateState");
            mount(<AsyncComponent />);

            assert(requestStub.calledOnce);
            assert(AsyncComponent.prototype._populateState.calledWith(data));
        });
    });

    describe("_populateState()", () => {
        it("should populate the state with user data returned from the GET", () => {
            const data = [
                { id: 1, name: "willson", utility: 88 },
                { id: 2, name: "jeffrey", utility: 102 }
            ];

            const wrapper = shallow(<AsyncComponent />);
            wrapper._populateState(data);

            expect(wrapper.state).to.deep.equal(data);
        });
    });
});
//asyncComponentTests.js
描述(“异步组件测试”,()=>{
描述(“componentDidMount()”,()=>{
它(“应该在componentDidMount上获取用户数据”,()=>{
常数数据={
记录:[
{id:1,名称:“willson”,实用程序:88},
{id:2,名称:“jeffrey”,实用程序:102}
]
};
const requestStub=sinon.stub(请求'get')。解析(数据);
sinon.spy(AsyncComponent.prototype,“\u populateState”);
mount();
断言(requestStub.calledOnce);
断言(AsyncComponent.prototype.\u populateState.calledWith(data));
});
});
描述(“_populateState()”,()=>{
它(“应该用GET返回的用户数据填充状态”,()=>{
常数数据=[
{id:1,名称:“willson”,实用程序:88},
{id:2,名称:“jeffrey”,实用程序:102}
];
常量包装器=浅();
包装器。填充测试(数据);
expect(wrapper.state).to.deep.equal(data);
});
});
});
注意:我仅从文档中编写了单元测试,因此使用
浅层
装载
断言
、和
预期
可能不是最佳实践。

那么,您认为呢