Stub called inside Promise then() doesn't have updated .called properties
lozadaOmr opened this issue · comments
Omar Lozada commented
-
Sinon version : 15.0.3
-
Environment : NodeJS
-
Other libraries you are using:
- bluebird
- mongoose
- mocha
What did you expect to happen?
- Should be able to have the following
findByIdStub.called
,secretsWriteStub.called
andnext.called
be equal to true on the test file
What actually happens
- Only the initial stub (
findByIdStub
) has the.called
equal to true, while the rest resulted in false - I know the stub.resolves work (eg: secretsWriteStub would resolve 'write stub secret')
- Just to compare when doing this on the function, all .called result in true:
testPromise () {
let user = this.services.secrets.write({ id: req.user._id })
next(user)
res.json(404)
return 'stop'
}
- This lead me think that any stubs called after the initial
stub.resolve()
is not behaving as expected
How to reproduce
- Only have two relevant files, and just run
gulp test
// middleware.js
'use strict'
class Middleware {
constructor (model, services, utils) {
this.services = services
this.model = model
this.utils = utils
}
testPromise () {
return (req, res, next) => {
return this.services.secrets.write({ id: req.user._id })
.then(secret => {
res.json(203)
next(false)
console.log(`within next --- `, next.called)
console.log(`within res --- `, res.json.called)
return 'ends here'
})
}
}
}
module.exports = Middleware
// middleware.test.js
'use strict'
global.Promise = require('bluebird')
const sinon = require('sinon')
const mongoose = require('mongoose')
const Secrets = require('path/to/stubbed/class') // secrets.write()
const Middleware = require('path/to/Middleware/class')
describe(`DEMO`, function () {
describe(`# testPromise ()`, function () {
let sandbox = null
let middleware = null
let model = null
let utils = null
let services = null
let req = null
let res = null
let next = null
let findByIdStub = null
let secretsWriteStub = null
before(function () {
sandbox = sinon.createSandbox()
req = { user: { _id: '1234890' } }
res = { json: sandbox.stub().returnsArg(0) }
let userResult = { userSecret: 'N3Kz+' }
findByIdStub = sandbox.stub(mongoose.Model, 'findById')
.usingPromise(global.Promise)
.withArgs(req.user._id).resolves(userResult)
model = { findById: findByIdStub }
secretsWriteStub = sandbox.stub(Secrets.prototype, 'write')
.usingPromise(global.Promise).resolves('write stub secret')
services = {
secrets: { write: secretsWriteStub }
}
utils = {}
})
afterEach(function () {
sandbox.restore()
})
it(`should run DEMO `, function (done) {
middleware = new Middlware(model, services, utils)
next = sandbox.stub().returnsArg(0)
let middlewareCall = middleware.testPromise()(req, res, next)
// assertion should go here but use console.log to prevent it from failing while debugging
console.log(`next stub ====> `, next.called)
console.log(`resJsonStub =====> `, res.json.called)
console.log(`secretswrite ====> `, secretsWriteStub.called)
done()
})
})
})
Omar Lozada commented
middlewareCall is a promise
So I did access stubbed next.called
, res.json.called
, secretsWriteStub.called
by adding a then block
middlewareCall
.then(() => {
// assertion now goes in here
console.log(`next stub ====> `, next.called)
console.log(`resJsonStub =====> `, res.json.called)
console.log(`secretswrite ====> `, secretsWriteStub.called)
done()
})
Only problem with this is that, when assertion fails I receive a an error, instead of telling me which assertion fails