需要帮助在 NodeJS 中使用 Sinon 存根异步 / 等待承诺

Posted

技术标签:

【中文标题】需要帮助在 NodeJS 中使用 Sinon 存根异步 / 等待承诺【英文标题】:Need help stubbing async / await promise with Sinon in NodeJS 【发布时间】:2019-12-19 05:34:29 【问题描述】:

我在控制器中调用了两个函数,它们返回一个承诺,当我运行测试时,它以expected stub to be called once but was called 0 times. 失败,但是如果我从控制器中删除这些承诺函数,它就可以正常工作。

FileTransferController.js

const  getIncomingFiles, getOutgoingFiles  = require('../services')

const controller = 

controller.getFileTransfers = async (req, res, next) => 
  try 
    const incoming = await getIncomingFiles()
    const outgoing = await getOutgoingFiles()
    return res.status(200).send( incoming, outgoing )
   catch (err) 
    return next(err)
  


module.exports = controller

FileTransferService.js

const service = 

const  Job  = require('../models')

service.getIncomingFiles = () => new Promise(async (resolve, reject) => 
  try 
    const jobs = await Job.findAll(
      where: 
        job_name: 'Some Job Name',
      ,
    )
    resolve(jobs)
   catch (err) 
    reject(err)
  
)

service.getOutgoingFiles = () => new Promise(async (resolve, reject) => 
  try 
    const jobs = await Job.findAll(
      where: 
        job_name: 'Some Job Name',
      ,
    )
    resolve(jobs)
   catch (err) 
    reject(err)
  
)

module.exports = service

这是我的单元测试。根据我从其他类似的堆栈溢出问题中读到的内容,我已经尝试了这 10 种不同的方法,但似乎没有任何效果。我觉得我目前拥有的是最接近的。

我的单元测试

const sinon = require('sinon')
const proxyquire = require('proxyquire')

let sandbox
let FileTransferController
let FileTransferService

beforeEach(() => 
  sandbox = sinon.createSandbox()
  FileTransferService = 
    getIncomingFiles: sandbox.stub().resolves([]),
    getOutgoingFiles: sandbox.stub().resolves([]),
  

  FileTransferController = proxyquire('../../../src/controllers/FileTransferController', 
    '../services': FileTransferService,
  )
)
afterEach(() => 
  sandbox.restore()
)

describe('FileTransferController.js', () => 
  describe('getFileTransfers()', () => 
    let req
    let res
    beforeEach(() => 
      req = 
      res = 
        send: sandbox.stub(),
        status: sandbox.stub().returns,
      
      FileTransferController.getFileTransfers(req, res)
    )
    it('should only call send once', () => 
      sinon.assert.calledOnce(res.send)
    )
  )
)

【问题讨论】:

【参考方案1】:

解决了这个问题。我没有尝试存根服务函数,而是代理查询服务并存根 sequelize 模型承诺函数。

const sinon = require('sinon')
const proxyquire = require('proxyquire')
const  Job  = require('../../../src/models')


let req
let res
let sandbox

before(() => 
  sandbox = sinon.createSandbox()
  req = 
  res = 
    send: sandbox.stub(),
    status: sandbox.stub().returns,
  
)
after(() => 
  sandbox.restore()
)

describe('FileTransferController.js', () => 
  beforeEach(async () => 
    sandbox.stub(Job, 'findAll').resolves()
    const FileTransferService = proxyquire('../../../src/services/FileTransferService', 
      Job,
    )
    const FileTransferController = proxyquire('../../../src/controllers/FileTransferController', 
      '../services/FileTransferService': FileTransferService,
    )
    await FileTransferController.getFileTransfers(req, res)
  )
  afterEach(() => 
    Job.findAll.restore()
  )
  describe('getFileTransfers()', () => 
    it('should only call send once', () => 
      sinon.assert.calledOnce(res.send)
    )
  )
)

【讨论】:

以上是关于需要帮助在 NodeJS 中使用 Sinon 存根异步 / 等待承诺的主要内容,如果未能解决你的问题,请参考以下文章

使用 Sinon 存根 window.location.href

如何使用 sinon 存根 new Date()?

轻松清理 sinon 存根

用 sinon 模拟/存根猫鼬 findById

如何使用 sinon 存根/模拟从“超类”复制的依赖项方法

如何使用 Sinon 存根 npm 包 `phin`