如何在笑话测试中模拟 'readline.createInterface'
How to mock 'readline.createInterface' in jest tests
我需要测试 '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) 一起工作?
问题是:在测试过程中没有触发异步可迭代对象。
解决方案,我们可以在 mock 中使用数组,如下所示:
jest.spyOn(readline, 'createInterface').mockImplementationOnce(() => {
return ['text1', 'text2'] as any
})
因为 for await(可迭代的常量项)适用于异步可迭代对象以及同步可迭代对象。使用同步迭代器,它们将自动执行。
我需要测试 '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) 一起工作?
问题是:在测试过程中没有触发异步可迭代对象。
解决方案,我们可以在 mock 中使用数组,如下所示:
jest.spyOn(readline, 'createInterface').mockImplementationOnce(() => {
return ['text1', 'text2'] as any
})
因为 for await(可迭代的常量项)适用于异步可迭代对象以及同步可迭代对象。使用同步迭代器,它们将自动执行。