【问题标题】:Using sinon to test a function in a promise使用 sinon 测试 promise 中的函数
【发布时间】:2018-11-22 23:42:16
【问题描述】:

我正在尝试测试 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()
    })
})

如果我运行这个,异步测试块会超时。有谁知道我应该如何处理这个?

谢谢!

【问题讨论】:

    标签: javascript node.js jestjs sinon


    【解决方案1】:

    问题

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

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

    解决方案

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

    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

    【讨论】:

    • 谢谢,我明白现在的工作原理以及我哪里出错了。这个答案很有帮助!
    猜你喜欢
    • 1970-01-01
    • 2015-12-01
    • 2017-10-13
    • 2017-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    相关资源
    最近更新 更多