【问题标题】:How to test callback functions with jest如何用 jest 测试回调函数
【发布时间】:2022-01-24 17:56:00
【问题描述】:

我正在尝试创建一个异步函数来创建一个文件并用玩笑对其进行测试。在我的代码中的某个时刻,我从 CreateWriteStream 调用 write,它需要一个回调并且开玩笑地抱怨这个函数没有被覆盖。

我的功能

import { createWriteStream } from 'fs'
import { CreateFileStorage, CreateFileStorageModel } from '../../../../data/protocols/create-file-storage'

export class CreateFileLocalStorage implements CreateFileStorage {
  async create (fileData: CreateFileStorageModel): Promise<boolean> {
    return await new Promise((resolve) => {
      const ws = createWriteStream(fileData.path)

      ws.write(fileData.buffer, (err) => {
        if (err) resolve(false) // jest's saying 'if path not taken | statement not covered'

        resolve(true)
      })
    })
  }
}

这是我的测试:

import { existsSync, stat } from 'fs'
import path from 'path'
import { CreateFileLocalStorage } from './file'

describe('Create File LocalStorage', () => {
  test('Should return false on failure', async () => {
    const createFileLocalStorage = new CreateFileLocalStorage()
    const buffer = Buffer.from('text to test')
    const file = {
      filename: 'test_file_creation.txt',
      path: path.resolve(__dirname, 'test_file_creation.txt'),
      size: buffer.byteLength,
      buffer
    }

    // I don't know what to do here to get that 100% coverage
  })

  // I have one more test here that is working fine, it tests the happy path
})

我的问题是,我如何模拟/测试这段代码以获得 100% 的覆盖率?

因为它是一个回调函数,所以我不知道如何测试它,并且很难在测试中故意制造失败

编辑:我快到了,并设法使测试与 jest.mock 一起工作,但是现在我的第二个测试失败了

jest.mock('fs', () => {
  return {
    createWriteStream: () => {
      return {
        write: (chunk: any, callback?: (error: Error) => void): boolean => {
          callback(new Error())
          return false
        }
      }
    }
  }
})

describe('Create File LocalStorage', () => {
  test('Should return false on failure', async () => {
    const createFileLocalStorage = new CreateFileLocalStorage()
    const buffer = Buffer.from('text to test')
    const file = {
      filename: 'test_file_creation.txt',
      path: path.resolve(__dirname, 'test_file_creation.txt'),
      size: buffer.byteLength,
      buffer
    }

    const promise = createFileLocalStorage.create(file)
    await expect(promise).resolves.toBeFalsy()
  })

  // this one now is failing, using `jest.clearMocks`
  // (actually any clear|reset jest function didn't work
  // the problem is that the module is still mocked at this point
  test('Should save file to disk on success', async () => {
    const createFileLocalStorage = new CreateFileLocalStorage()
    const buffer = Buffer.from('text to test')
    const file = {
      filename: 'test_file_creation.txt',
      path: path.resolve(__dirname, 'test_file_creation.txt'),
      size: buffer.byteLength,
      buffer
    }

    const created = await createFileLocalStorage.create(file)
    expect(created).toBe(true)
    expect(existsSync(file.path)).toBe(true)

    stat(file.path, (err, status) => {
      expect(err).toBeNull()

      const isFile = status.isFile()
      const size = status.size

      expect(isFile).toBe(true)
      expect(size).toBe(file.size)
    })
  })
})

【问题讨论】:

    标签: node.js typescript jestjs


    【解决方案1】:

    createWriteStream 返回类WriteStream 的实例,因此您可以通过窥探原型来模拟write 实例方法。

    jest.spyOn(WriteStream.prototype, 'write').mockImplementation((buffer, cb) => {
      cb('this is an error')
    })
    
    expect(createFileLocalStorage.create('...')).resolves.toBeFalsy()
    

    【讨论】:

    • 差不多了,监视 WriteStream 对我不起作用,但我设法使用 jest.mock 并制作了一个与您的稍有不同的模拟。我的第一个测试现在确实有效,但是,第二个测试现在失败了,我试图清除模拟但无济于事。另外,我的jest.mock 位于文件的顶部,如果我将其移至测试它会失败
    猜你喜欢
    • 2019-09-21
    • 2021-08-08
    • 1970-01-01
    • 2020-01-24
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    相关资源
    最近更新 更多