为什么在模拟 Node.js 模块时 Jest 模拟实例为空?

mik*_*ikl 3 javascript unit-testing jestjs

我在模拟方面遇到一些问题,我通过添加模拟/ssh2-sftp-client.ts文件来模拟节点模块:

const mockSsh2SftpClient = jest.fn().mockImplementation(() => {
  return {
    connect: async () => {},
    end: async () => {},
    on: () => {}
  }
})

export default mockSsh2SftpClient
Run Code Online (Sandbox Code Playgroud)

这有效,有点。我的测试使用此模拟正确运行,但在测试中 SftpClient.mock.instances[0] 是一个空的 mockConstructor {} 对象,而不是此模拟(即 SftpClient.mock.instances[0].end 未定义)。我究竟做错了什么?作为参考,我的测试代码如下所示:

import { ConnectConfig } from 'ssh2'
import SftpClient from 'ssh2-sftp-client'
import { withSftp } from '../sftp'

// Type assertion to make TypeScript happy.
const MockSftpClient = SftpClient as jest.Mock<SftpClient>

describe(withSftp, () => {
  const mockConnectionConfig: ConnectConfig = {}

  beforeEach(() => {
    // Clear all instances and calls to constructor and all methods:
    MockSftpClient.mockClear()
  })

  it('should call the callback after successfully connecting', async () => {
    const mockCallback = jest.fn()

    // Instantiates SftpClient and calls connect, then the callback, then end.
    await withSftp(mockConnectionConfig, mockCallback)

    const mockInstance = MockSftpClient.mock.instances

    expect(mockCallback).toHaveBeenCalledTimes(1)
    expect(MockSftpClient.mock.instances[0].end).toHaveBeenCalledTimes(1)
  })
})
Run Code Online (Sandbox Code Playgroud)

最后一个失败,因为 MockSftpClient.mock.instances[0].end 未定义,它应该是一个函数。

Bri*_*ams 7

提供的模拟构造函数Jest 仅记录this为实例,因此如果您的模拟构造函数返回不同的对象,则该对象将不会记录在数组中instances

要获得您想要的行为,只需使用标准函数进行模拟并使用this

__mocks__/ssh2-sftp-client.ts

const mockSsh2SftpClient = jest.fn(function() {
  this.connect = jest.fn();
  this.end = jest.fn();
  this.on = jest.fn();
});

export default mockSsh2SftpClient
Run Code Online (Sandbox Code Playgroud)

  • 对于那些在这里几个小时拉扯剩下的小头发的人来说,重点是:导出模拟 `export default &lt;your-mock&gt;` 是基础,否则,模拟对象将为空...... (2认同)