【问题标题】:How to mock 'readline.createInterface' in jest tests如何在玩笑测试中模拟“readline.createInterface”
【发布时间】:2022-01-21 09:26:23
【问题描述】:

我需要测试“readline.createInterface”。

下面是我需要测试的代码:

private createReadStreamSafe(filePath: string): Promise<fs.ReadStream> {
        return new Promise((resolve, reject) => {
          const fileStream = fs.createReadStream(filePath)
          console.log('file Stream')
          fileStream
            .on('error', () => {
              reject('create read stream error')
            })
            .on('open', () => {
              resolve(fileStream)
            })
        })
      }
    
      async start() {
        const fileStream = await this.createReadStreamSafe(this.filePath)
    
        const rl = readline.createInterface({
          input: fileStream,
          output: process.stdout,
          terminal: false
        })
    
        for await (const line of rl) {
          ...
        }
      }

我尝试了以下代码:

it('should work', async () => {
    const mockedReadStream = new Readable()
    jest.spyOn(fs, 'createReadStream').mockReturnValue(mockedReadStream as any)
    jest.spyOn(readline, 'createInterface').mockImplementation(() => {
      const lines = ['text', 'text2', 'text3']

      return {
        [Symbol.asyncIterator]() {
          return {
            i: 0,
            next: () => {
              if (this.i < 3) {
                return Promise.resolve({ value: lines[this.i++], done: false })
              }

              return Promise.resolve({ done: true })
            }
          }
        }
      } as any
    })

    const app = new App('myFile.txt')

    let promise = app.start()
    mockedReadStream.emit('open')
    await expect(promise).resolves.toBe(undefined)
  })

但以下代码永远无法到达

for await (const line of rl) {
...
        }

有没有办法模拟 readline.createInterface 然后它与 for await (const line of rl) 一起工作?

【问题讨论】:

    标签: node.js unit-testing mocking readline


    【解决方案1】:

    问题是:测试期间没有触发异步可迭代对象。

    解决方案,我们可以在 mock 中使用一个数组,像这样:

    jest.spyOn(readline, 'createInterface').mockImplementationOnce(() => {
          return ['text1', 'text2'] as any
        })
    

    因为等待(可迭代的常量项)适用于异步可迭代对象以及同步可迭代对象。使用同步迭代,它们将自动执行。

    【讨论】:

      猜你喜欢
      • 2022-01-21
      • 1970-01-01
      • 2018-09-18
      • 2021-06-16
      • 2020-04-28
      • 2017-11-19
      • 2018-12-28
      • 2021-04-27
      • 1970-01-01
      相关资源
      最近更新 更多