如何在玩笑测试中模拟节点 'createReadStream' 和 'readline.createInterface'
How to mock node 'createReadStream' and 'readline.createInterface' in jest tests
我在为涉及 'createReadStream' 和 '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.only('should create an error if creating the read stream from the file path fails', () => {
const mockedReadStream = new Readable()
jest.spyOn(fs, 'createReadStream').mockReturnValue(mockedReadStream as any)
const app = createApp('invalid/file/path')
expect.assertions(1)
try {
app.start()
mockedReadStream.emit('error', 'Invalid file path')
} catch (error) {
expect(getErrorMessage(error)).toBe('Invalid file path')
}
})
但是,我得到了这个:
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
^
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "undefined".] {
code: 'ERR_UNHANDLED_REJECTION'
}
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
模拟导致未处理的拒绝承诺。测试应该是异步的并且 return 一个承诺,即 async
。 try..catch
无法在同步函数中处理。
由于在调用 mockedReadStream.emit 时承诺被拒绝,因此需要在承诺被拒绝后立即与 catch 链接,例如通过 Jest 承诺断言:
let promise = app.start()
mockedReadStream.emit('error', 'Invalid file path')
await expect(promise).rejects.toThrow('Invalid file path')
这揭示了测试单元中的问题,因为 reject()
没有传递错误。
我在为涉及 'createReadStream' 和 '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.only('should create an error if creating the read stream from the file path fails', () => {
const mockedReadStream = new Readable()
jest.spyOn(fs, 'createReadStream').mockReturnValue(mockedReadStream as any)
const app = createApp('invalid/file/path')
expect.assertions(1)
try {
app.start()
mockedReadStream.emit('error', 'Invalid file path')
} catch (error) {
expect(getErrorMessage(error)).toBe('Invalid file path')
}
})
但是,我得到了这个:
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
^
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "undefined".] {
code: 'ERR_UNHANDLED_REJECTION'
}
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
模拟导致未处理的拒绝承诺。测试应该是异步的并且 return 一个承诺,即 async
。 try..catch
无法在同步函数中处理。
由于在调用 mockedReadStream.emit 时承诺被拒绝,因此需要在承诺被拒绝后立即与 catch 链接,例如通过 Jest 承诺断言:
let promise = app.start()
mockedReadStream.emit('error', 'Invalid file path')
await expect(promise).rejects.toThrow('Invalid file path')
这揭示了测试单元中的问题,因为 reject()
没有传递错误。