0

案例是编写一个单元测试uploadFile,应该使用 Jest 将文件上传到 Google Storage 存储桶并模拟createReadStreamFile 对象上的函数。

my-service.ts

async uploadFile(file: FileUpload): Promise<{
url: string
path: string}> {
 try {
  file.createReadStream().pipe(
   bucket
    .createWriteStream({
     ...some options
    })
    .on('error', (err) => {
     reject(err)})
    .on('finish', async () => {
     resolve({
      url: 'file-url',
      path: 'file-path'
     })
    })
   
 }
}

my-service.spec.ts

  describe('#uploadFile', () => {
    it('uploads file', async () => {
      const bucketMock = new Bucket('the-bucket-mock')
      const bucketFileMock = new File(bucketMock, 'the-file')

      const fileUploadMock = {
        filename: 'the-file',
        mimetype: 'mimetype',
        encoding: 'encoding',
        createReadStream: jest.fn().mockImplementation((stream) => {
          pipe: jest.fn()
        }),
      }

      jest
        .spyOn(fileUploadMock, 'createReadStream')
        .mockImplementation((stream) => {
          stream.pipe()
          return Promise.resolve({
            url: 'url-result',
            path: 'file-path-result',
          })
        })

      const uploadFileResult = await myService.uploadFile(fileUploadMock)

      expect(uploadFileResult).toBeCalled()
    })
  })
4

1 回答 1

1

这部分代码:

        createReadStream: jest.fn().mockImplementation((stream) => {
          pipe: jest.fn()
        }),

没有做你认为它正在做的事情。您认为您传入的函数正在mockImplementation返回一个看起来像 的对象{pipe: jest.fn()},但是,事实并非如此。如果箭头函数在箭头之后遇到的第一件事是一个开放的大括号,那么现在它告诉 TS/JS 你在一个函数体内,它不再具有隐式返回。类似于如果你写的:

// Nothing happens here, and it returns undefined
function (stream) {
  pipe: jest.fn()
}

对此的解决方法是:

(stream) => {
  return { pipe: jest.fn() };
}

或者,如果您想保持箭头运算符的简洁性,您只需要确保箭头之后的第一件事不是大括号,即:

// Parenthesis help! 
(stream) => ({
  pipe: jest.fn()
})
于 2021-04-01T11:58:50.613 回答