当前位置: 首页 > 面试题库 >

Enzyme error:“方法'setState'仅应在单个节点上运行。找到了3个。”

幸阳波
2023-03-14
问题内容

我对使用React应用程序上的酶/ Jest进行测试还很陌生,所以我设置测试的方式可能有些问题。

我特别想在组件中测试一个功能: reviewCandidate()

reviewCandidate() {
  const { candidate_id: candidateId, } = this.props.match.params;
  const { latest_application_id: latestApplication, } = this.state.candidateInfo;
  const { expressApi, } = this.props;
  /** @todo Define user when authentication is in place */
  const user = 'undefined';
  expressApi.addReviewedCandidate(
    parseInt(candidateId, 10),
    latestApplication,
    user,
    // comment,
  ).then(() => {
    // If the API call is successful, have the state reflect this accordingly
    this.setState({
      reviewInfo: {
        candidate_id: candidateId,
        last_application_reviewed: latestApplication,
        user,
        // comment: comment
      },
    });
    // Pop-up a snackbar indicating a successful review
    this.props.setSnackbar({
      open: true,
      message: <span>Candidate_{candidateId} marked as reviewed</span>,
    });
  });
}

使用Web应用程序时,它可以正常工作而不会发出任何警告。当我尝试使用Jest / Enzyme测试它时,就会出现问题。

这是我为上述功能编写的测试:

describe('Reviewing Candidates', () => {
  const mockCandidateReviewStatus = [];
  const mockApplicationsOfCandidate = {/* mock data */};

  const mockExpressApi = {
    applicationsOfCandidate() {
      return new Promise(resolve => resolve(mockApplicationsOfCandidate));
    },
    candidateReviewStatus() {
      return new Promise(resolve => resolve(mockCandidateReviewStatus));
    },
    addReviewedCandidate() {
      return new Promise(resolve => resolve());
    },
  };
  const handleError = error => error;
  it('ensures reviewedCandidates() is called correctly', async() => {
    const setSnackbar = jest.fn(() => 'foobar');
    const wrapper = shallow(
      <Candidate
        expressApi={mockExpressApi}
        handleError={handleError}
        match={{
          params: {
            candidate_id: 153,
          },
        }}
        utils={utils}
        setSnackbar={setSnackbar}
      />
    );
    /**
     * These wrapper.update() calls ensure componentDidMount() finish setting
     * the state of the component
     *
     * Unsure if this is the best way to deal with waiting for 
     * componentDidMount() to finish
     */
    await wrapper.update();
    await wrapper.update();
    await wrapper.instance().reviewCandidate();
    /**
     * @todo: Check this.state.reviewInfo is set as expected
     */
    expect(setSnackbar).toHaveBeenCalled();
  });
});

但是await wrapper.instance().reviewCandidate()通话使酶崩溃。

Error: Method “setState” is only meant to be run on a single node. 3 found instead.
    at ShallowWrapper.single (/path/to/project/node_modules/enzyme/build/ShallowWrapper.js:1828:17)
    at ShallowWrapper.setState (/path/to/project/node_modules/enzyme/build/ShallowWrapper.js:575:14)
    at Candidate.ShallowWrapper.instance.setState (/path/to/project/node_modules/enzyme/build/ShallowWrapper.js:217:35)
    at expressApi.addReviewedCandidate.then (/path/to/project/src/components/Candidate.js:514:12)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

如果我注释掉this.setState调用的.then()API调用后:

reviewCandidate() {
  // ...
  expressApi.addReviewedCandidate(
    // ...
  ).then(() => {
    // If the API call is successful, have the state reflect this accordingly
    /*
    this.setState({
      reviewInfo: {
        candidate_id: candidateId,
        last_application_reviewed: latestApplication,
        user,
        // comment: comment
      },
    });
    */
    // Pop-up a snackbar indicating a successful review
    this.props.setSnackbar({
      open: true,
      message: <span>Candidate_{candidateId} marked as reviewed</span>,
    });
  });
}

然后测试可以正常进行:

 PASS  test/Candidate.test.js (15.954s)
 PASS  test/Main.test.js

Test Suites: 2 passed, 2 total
Tests:       17 passed, 17 total
Snapshots:   0 total
Time:        20.378s
Ran all test suites related to changed files.
----------------------------|----------|----------|----------|----------|-------------------|
File                        |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------------------------|----------|----------|----------|----------|-------------------|
All files                   |    31.05 |    24.58 |    23.04 |    31.88 |                   |
 src                        |        0 |        0 |        0 |        0 |                   |
  index.js                  |        0 |        0 |        0 |        0 |   1,2,3,4,5,6,7,9 |
 src/components             |    43.93 |    38.41 |    33.86 |    44.92 |                   |
  Candidate.js              |    62.41 |    60.87 |       50 |    62.59 |... 88,489,492,616 |
  Main.js                   |    92.31 |    88.89 |    79.31 |    92.21 |... 34,342,354,363 |
----------------------------|----------|----------|----------|----------|-------------------|

万一有关系,这里是componentDidMount()在测试中调用Mock API调用的同一组件中的函数:

componentDidMount() {
    const candidateId = this.props.match.params.candidate_id;
    Promise.all([
      this.props.expressApi.applicationsOfCandidate(candidateId),
      this.props.expressApi.candidateReviewStatus(candidateId),
    ]).then((data) => {
      const candidateInfo = data[0][this.props.match.params.candidate_id];
      const reviewInfo = data[1][0];
      this.setState({ /* Sets various state parameters based on what was returned from the API calls*/ });
    }).catch((err) => {
      this.props.handleError(err);
      this.setState({
        error: err,
      });
    });
}

我在做什么是造成这种情况的原因Error: Method “setState” is only meant to be run on a single node. 3 found instead.

如果需要提供有关组件本身的更多信息,请告诉我。

在此先感谢您的帮助。


问题答案:

wrapper.update()不应该在那里。它不会返回承诺,也不能被await编辑。默认情况下,酶已经运行了生命周期挂钩,包括componentDidMount

这个问题是componentDidMount不可测试的,并且不能兑现承诺。应该将其提取为返回可以链接的promise的方法:

loadSomething() {
    const candidateId = this.props.match.params.candidate_id;

    return Promise.all([
      this.props.expressApi.applicationsOfCandidate(candidateId),
      this.props.expressApi.candidateReviewStatus(candidateId),
    ]).then((data) => {
      const candidateInfo = data[0][this.props.match.params.candidate_id];
      const reviewInfo = data[1][0];
      this.setState({ ... });
    }).catch((err) => {
      this.props.handleError(err);
      this.setState({
        error: err,
      });
    });
}

componentDidMount() {
    this.loadSomething();
}

然后可以将其存入一个测试中:

jest.stub(Candidate.prototype, 'loadSomething')
shallow(<Candidate .../>);
expect(shallow.instance().loadSomething).toHaveBeenCalledTimes(1);

并直接在另一个中进行测试:

shallow(<Candidate .../>, { disableLifecycleMethods: true });
await shallow.instance().loadSomething();
expect(shallow.state(...))...


 类似资料:
  • 我的问题是我的pyspark作业没有并行运行。 代码和数据格式: 我的PySpark如下所示(显然是简化的): PySpark的全部要点是并行运行这个东西,显然不是这样。我在各种集群配置中运行了这些数据,最后一个配置是大量的,这时我注意到它是单一节点使用的。因此,为什么我的工作需要很长时间才能完成,而时间似乎与集群规模无关。 所有较小数据集的测试在我的本地机器和集群上都没有问题。我真的只是需要高档

  • 我对在Mesos上测试Spark运行感兴趣。我在Virtualbox中创建了一个Hadoop2.6.0单节点集群,并在其上安装了Spark。我可以使用Spark成功地处理HDFS中的文件。

  • 我编写了一个通用管道,它接受几个参数,以便将预定义GitHub存储库中的版本部署到特定节点。我想将这个管道托管在GitHub上的Jenkinsfile上,所以我将作业配置为使用“来自SCM的管道脚本”。事实是,当我尝试构建作业时,Jenkinsfile在每个节点上都被签出。是否可以仅在主节点上签出和执行Jenkinsfile,并按预期运行管道? 编辑:正如我之前所说,管道工作得很好,并且按照预期将

  • 问题内容: 通过下载并安装Visual Studio Code 1.2.1版本,并在工作目录中放置64位版本的node.exe msi(我认为这是正确的),我们如何添加node和npm命令行工具?我们的路径?我对理解这一说法感到困惑。我们在哪里以及如何实施?我直接从此资源页面的顶部引用了此要求- https: //code.visualstudio.com/Docs/runtimes/nodejs

  • C:\Windows\system 32 C:\Program Files\Apache软件基金会\Apache-maven-3.2。2\bin“C:\Windows\S 系统32;C:\ProgramFiles(x86)\Heroku\bin;C:\ProgramFiles\nodejs\;C:\Git\cmd;C: \Git\bin;C:\ProgramFiles\apache-ant-1.9

  • 我正在Azure中的Hadoop中创建一个多节点(1主3从)集群,我想所有的设置都已经完成了,但是当我运行一个测试文件时,它遇到了与Stackoverflow中的其他类似的问题,我尝试了他们的解决方案,但是,这个问题仍然无法解决。谁能帮帮我吗?我在这个问题上困了几天了 我检查了hadoop-hduser-namenode-master.log并得到了一些错误,似乎Damenode无法与nameno