繁体   English   中英

通过异步setState调用来响应测试功能

[英]react testing function with asynchronous setState call

我的React组件中有以下功能

changeProject(project) {
    const buildProjectValues = [];
    BambooService.GetBuilds(project).then((res) => {
      res.map(build => {
        buildProjectValues.push({'label':build.searchEntity.planName, 'value':build.searchEntity.id});
      });
      this.setState({buildValues:buildProjectValues})
    })
  }

与关联的测试:

it('should set buildValues state property to returned array from API call', () => {
    const wrapper = mount(<RepoForm projectValues={projectOptions} />);
    const instance = wrapper.instance();

    nock('https://myurl.api.com')
      .get('/builds?projectKey=KEY')
      .reply(200, buildMock)

    instance.changeProject('KEY');
    expect(instance.state.buildValues).to.equal(buildMock);
  })

问题是在我的代码中的诺言得以解决之前,我的测试以失败告终,而且setState还是异步的!

我已经尝试过使用setImmediate,如下所示,但结果相同。

it('should set buildValues state property to returned array from API call', () => {
    const wrapper = mount(<RepoForm projectValues={projectOptions} />);
    const instance = wrapper.instance();

    nock('https://myurl.api.com')
      .get('/builds?projectKey=KEY')
      .reply(200, buildMock)

    instance.changeProject('KEY');
    setImmediate(() => {
      expect(instance.state.buildValues).to.equal(buildMock);
    });

  })

有什么办法可以重写我的代码来避免这种情况? 还是在这种情况下可以使用其他模式来测试异步代码? 谢谢!

首先编辑changeProject()以返回在测试中使用它的承诺:

changeProject(project) {
    const buildProjectValues = [];
    return BambooService.GetBuilds(project).then((res) => {
      res.map(build => {
        buildProjectValues.push({
           'label':build.searchEntity.planName,
           'value':build.searchEntity.id
        });
      });
      this.setState({buildValues:buildProjectValues})
    })
  }

然后在测试中,将您的断言添加到then()

it('should set buildValues state property to returned array from API call', () => {
    const wrapper = mount(<RepoForm projectValues={projectOptions} />);
    const instance = wrapper.instance();

    nock('https://myurl.api.com')
      .get('/builds?projectKey=KEY')
      .reply(200, buildMock)

    instance.changeProject('KEY')
       .then(() => {
            expect(instance.state.buildValues).to.equal(buildMock);
       });    
  })

您也可以使用await代替then()

await instance.changeProject('KEY');     
expect(instance.state.buildValues).to.equal(buildMock);

修改changeProject()以返回承诺:

changeProject(project) {
    const buildProjectValues = [];
    return BambooService.GetBuilds(project).then((res) => {
      res.map(build => {
        buildProjectValues.push({'label':build.searchEntity.planName, 'value':build.searchEntity.id});
      });
      this.setState({buildValues:buildProjectValues})
    })
}

现在,您可以在测试中获得promise,并允许Jest在调用expect()之前解决它:

it('should set buildValues state property to returned array from API call', () => {
    const wrapper = mount(<RepoForm projectValues={projectOptions} />);
    const instance = wrapper.instance();

    nock('https://myurl.api.com')
      .get('/builds?projectKey=KEY')
      .reply(200, buildMock)

    return instance.changeProject('KEY')
        .then(() => {
          expect(instance.state.buildValues).to.equal(buildMock);
        });
})

当您从Jest测试返回承诺时,Jest将尝试解决它。 如果成功解决了诺言, then()将调用then()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM