首页 > 解决方案 > 如何用单元测试覆盖 Promise.all(...) 语句

问题描述

我无法在 componentDidMount 方法的 setTimeout() 块中运行的异步函数 (loadMessages()) 中编写涵盖 Promise.all() 语句的测试。

在 componentDidMount 中有一个在 setTimeout 回调中调用的 this.loadMessages() 函数,为了让我完成我的测试,我需要执行 loadMessages()。

componentDidMount() {
    const { conversationId } = this.state
    const POLLING_INTERVAL = 3000

    if (conversationId) {
      setTimeout(() => this.loadMessages(), 0)
      this.timer = setInterval(() => this.loadMessages(), POLLING_INTERVAL)
    } else {
      this.setState({ loading: false })
    }
  }

我解决了 setTimeout 回调


await new Promise(resolve =>
      setTimeout(() => {
        resolve()
      }, 3000)
    )

这解决了一个函数调用,但是当开始执行一个函数时,报告覆盖率说 Promise.all 没有被覆盖,函数本身看起来像:


async loadMessages() {
    const { messages, conversationId, errors } = this.state
    let messagesWithAuthors

    // initial load
    if (messages.length === 0) {
      try {
        let initialMessages = await runtime.dais.communication.auto.getMessagesByConversationId(
          conversationId
        )

        const messageAuthors = await Promise.all(
          initialMessages.map(async message =>
            //runtime.dais.orgService.auto.getPersonById(message.sender.id)
            runtime.dais.organization.auto.getPersonById(message.sender.id)
          )
        )

        messagesWithAuthors = initialMessages.map((message, i) => ({
          ...message,
          author: messageAuthors[i],
        }))

        this.setState({
          messages: messagesWithAuthors,
          messageAuthors,
          loading: false,
        })
      } catch (error) {
        this.setState({ errors: [...errors, error], hasErrors: true, modalOpen: true })
      }
    } else {
      let updatedMessages = await runtime.dais.communication.auto.getMessagesByConversationId(
        conversationId
      )
      this.checkIfNeedUpdate(updatedMessages)
    }
  }

有什么方法可以模拟从 Promise.all() 返回的值到 messageAuthors 变量中?我正在使用@testing-library/react 进行测试,我的测试看起来像这样

 it('ensure that we have chat window shown if we have conversation as a prop', async () => {
    const queries = render(
      <CommWidget runtime={runtime} conversationId="fe3d52fc-ffb3-482a-aedf-79000645ca70" />
    )
    await new Promise(resolve =>
      setTimeout(() => {
        resolve()
      }, 3000)
    )

    const commWidget = queries.container.querySelector(
      '.ui-comm-widget .ui.segments.comm-widget #chat-window'
    )

    expect(commWidget).toBeInstanceOf(HTMLDivElement)
  })

标签: reactjsjestjsreact-testing-library

解决方案


请不要在您的测试中设置超时,这是一种反模式。承诺解决后会发生什么?页面会变吗?如果是这样,请等待更改出现。有关测试异步方法的介绍,请参阅本文。


推荐阅读