annedroiid annedroiid - 1 month ago 9
TypeScript Question

Can't return more than one value from a sinon stub

I have a method that I want to stub using sinon, so that the first time it is called it returns one value, and then returns a different value on the second call. However currently only the first value is being returned. My code is in Typescript and uses Sinon and Bluebird (promises).

import sinon = require('sinon')
import * as MyService from "../main/Service"
import * as Promise from "bluebird"

it("test things", function(done) {
let serviceStub = sinon.stub(MyService, 'method')

serviceStub.onFirstCall().returns(Promise.reject("rejected"))
.onSecondCall().returns(Promise.resolve("resolved"))

MyService.method().then(function(value) {
console.log("success 1: "+value.value())
}, function(error) {
console.log("error 1: "+error)
})

MyService.method().then(function(value) {
console.log("success 2: "+value.value())
}, function(error) {
console.log("error 2: "+error)
})

done()
})


I presume I must be doing something wrong with the stubbing as this is the first time I have used sinon. If it returns
Promise.reject("rejected")
and then
Promise.resolve("resolved")
as I would expect it to, it would have the following output.

error 1: rejected
success 2: resolved


However it just prints out the same error both times, so the
onSecondCall()
method isn't working. The first value I gave it,
Promise.reject("rejected")
, is being returned both times the method is called.

error 1: rejected
error 2: rejected


Does anyone know what I'm doing wrong with my stubbing?

Note: For anyone unfamiliar with bluebird/promises, in the method
then(function(value){}, function(error){})
the first function handles what happens if the promise is resolved and the second function handles what happens if the promise is rejected .

Answer

I think your usage is probably correct, but the dependencies are messing up; due to the following test:

I tried your example (for simplicity in js since there were only import statements from es6/typescript) and with slight modifications it works as intended.

So perhaps by removing taking one step at a time from the working to broken can show you which component is misbehaving.

The following code uses native Promises from Node v6.6 with value.value() replaced by simply value, as string does not contain a method 'value'

let sinon = require('sinon')

let MyService = { method() {}}

let serviceStub = sinon.stub(MyService, 'method')

serviceStub.onFirstCall().returns(Promise.reject("rejected"))
    .onSecondCall().returns(Promise.resolve("resolved"))

MyService.method().then(function (value) {
    console.log("success 1: " + value)
}, function (error) {
    console.log("error 1: " + error)
})

MyService.method().then(function (value) {
    console.log("success 2: " + value)
}, function (error) {
    console.log("error 2: " + error)
})

returns

>node sinon.js                              
error 1: rejected                                                           
success 2: resolved  
Comments