I wanna understand if Sinon can be used to stub a function from another class that is called internally.
For example there is a dbutil class:
class DBUtils {
getMyResult(var1, var2){
return new Promise((resolve) => {
console.log("calling real getMyResult");//I still see this in the log
resolve(var1 + var2);
});
}
}
module.exports = DBUtils;
It is called in another class dummyService:
const dbUtils = new DBUtils();
class dummyService {
getResult(var1, var2){
//initially in my code, it returns a promise,
//but I have replaced it with your code
return dbUtils.getMyResult(var1, var2).then(item =>{
console.log("finish getting my result!");
console.log("here is my result: " + item);
return item;
});
}
module.exports = dummyService;
Here is my unit test file: (Applied code change suggested by @Mark_M)
describe("dummy Test", function () {
var service = new DummyService();
const stub = sinon.stub(DBUtils.prototype, 'getMyResult');
stub.resolves("1234");
it("get result", function() {
service.getResult("ab", "cd").then(item => {
console.log(item);
});
});
});
Can anyone help me understand why my Stub is not working? and How could I stub the getMyResult function inside dbUtil class?
================ SOLUTION ===================
There are 2 things I missed:
sinon.stub(DBUtils.prototype, 'getMyResult').resolves("1234");
inside dummyService, I have
const DBUtils = require(./dbutils);
however, in the test file, I have
const DBUtils = require(./DBUtils);
Somehow, sinon didn't complained about it, and that's why my stub get never injected in the original method....after I correct the import in my test, I can see the stub result get injected now.
Since getMyResult()
is a class method on your DBUtils
class, you need to stub the prototype of DBUtils
. Something like this:
DBUtils.getMyResult()
returns a promise. So you don't need to re-wrap it in a promise in dummyService.getResult()
. It makes it a lot easier to reason about (and test) if you just return the original promise:
dummyService:
const DBUtils = require('./DBUtils')
class dummyService {
getResult(var1, var2){
const dbUtils = new DBUtils() // <- I assume you are making an instance somewhere
return dbUtils.getMyResult(var1, var2).then(item =>{
console.log("finish getting my result!");
console.log("here is my result: " + item);
return item // <- if you want to access item in then you need to return it
});
}
}
module.exports = dummyService;
Now in test.js:
const DBUtils = require('./DBUtils')
const DummyService = require('./dummy')
const sinon = require('sinon')
// stub the prototype
const stub = sinon.stub(DBUtils.prototype, 'getMyResult')
stub.resolves("Stubbed: 1234")
// make an instance of the service
const service = new DummyService()
service.getResult("ab", "cd").then(item => {
console.log(item)
// this prints 'stubbed: 1234'
// item is "abcd", which is the returned value of the real getMyResult method.
// the expectation is, item should be "1234" as specified in the stub.
});