如何在玩笑测试中模拟“readline.createInterface”
Posted
技术标签:
【中文标题】如何在玩笑测试中模拟“readline.createInterface”【英文标题】:How to mock 'readline.createInterface' in jest tests 【发布时间】: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) 一起工作?
【问题讨论】:
【参考方案1】:问题是:测试期间没有触发异步可迭代对象。
解决方案,我们可以在 mock 中使用一个数组,像这样:
jest.spyOn(readline, 'createInterface').mockImplementationOnce(() =>
return ['text1', 'text2'] as any
)
因为等待(可迭代的常量项)适用于异步可迭代对象以及同步可迭代对象。使用同步迭代,它们将自动执行。
【讨论】:
以上是关于如何在玩笑测试中模拟“readline.createInterface”的主要内容,如果未能解决你的问题,请参考以下文章
用玩笑进行单元测试时,如何以角度模拟 ResizeObserver polyfill?
在“if”语句中没有调用模拟函数 - 用玩笑和酶反应应用程序测试?