使用 sinon 测试 promise 中的函数

Using sinon to test a function in a promise

我正在尝试测试 mysqlite3 数据访问层,但我似乎无法正确存根我的 db.all() 方法,我不确定这是由于我的数据库是如何传入的还是我是否我打错了。

这是我的数据库文件:

const db = new sqlite3.Database(path.join(__dirname, ' 
../database/example.db'), (err) => {
    if (err) return console.log(err.message)
    console.log('Connected to the database')
})

module.exports.database = db

这是我要存根的函数:

const db = require('./database.js').database

module.exports.selectMultiple = request => {
    //unimportant code
    return new Promise((resolve, reject) => {
        db.all(sql, (err, rows) => {
            if (err)
                reject(err)
            else {
                resolve('blah blah blah')
        })
    })
}

这是我的尝试,但我似乎无法开始工作:

const db = require('../../data_access/database.js').database

describe('select multiple', () => {
    beforeEach(() => {
        const testProduct2 = JSON.parse(JSON.stringify(testProduct))
        testProduct2['key'] = '2'
        this.multiple = sinon.stub(db, 'all')
            .resolves([testProduct, testProduct2])
    })

    afterEach(() => {
        this.multiple.restore()
    })

    test('select 2 products', async(done) => {
        expect.assertions(2)
        const macbooks = await productDb.selectMultiple({amount: 2})
        expect(macbooks.length === 2).toBe(true)
        expect(macbooks[0].key !== macbooks[1].key).toBe(true)
        done()
    })
})

如果我运行这个异步测试块超时。有谁知道我应该如何解决这个问题?

谢谢!

问题

db.all 不是 return Promise,它使用回调作为第二个参数。

stub.resolves 导致存根 return Promise,因此永远不会调用回调,并且由 selectMultiple 编辑的 Promise return 永远不会解析导致测试超时await productDb.selectMultiple({ amount: 2 }).

解决方案

Stub db.all 使用 stub.callsArgWith 以便调用作为第二个参数传递的回调:

describe('select multiple', () => {
  beforeEach(() => {
    const testProduct2 = JSON.parse(JSON.stringify(testProduct))
    testProduct2['key'] = '2'
    this.multiple = sinon.stub(db, 'all')
      .callsArgWith(1, null, [testProduct, testProduct2]);  // use stub.callsArgWith
  })

  afterEach(() => {
    this.multiple.restore()
  })

  test('select 2 products', async () => {
    expect.assertions(2)
    const macbooks = await productDb.selectMultiple({ amount: 2 })
    expect(macbooks.length === 2).toBe(true)  // SUCCESS
    expect(macbooks[0].key !== macbooks[1].key).toBe(true)  // SUCCESS
  })
})

另请注意,您不需要使用 done,因为您正在使用 async 测试函数并且在调用 productDb.selectMultiple 时使用 await