Sinon - basic use with internal functions

2.4k views Asked by At

I'm having trouble getting the basics of testing my code using sinon. I have a simple module that calls two internal functions and checks their result. I was to use a stub to vary the output of these functions to test how the module responds. Is this possible?

scripts.js

let check1 = function(){return true}
let check2 = function(){return true}
let startFunc = function(){console.log('checks Passed')}
let sendLog = function(message){console.log(message)}

module.exports.check=function(){

    console.log('check1: ', check1())
    console.log('check2: ', check2())

    if (!check1() || !check2()) {
        startFunc()
        sendLog("started")
    }
}

test.js:

"use strict";
var chai = require("chai");
var sinon = require("sinon");
var sinonChai = require("sinon-chai");
var expect = chai.expect;
chai.use(sinonChai);

var scripts = require('./scripts')

describe("scripts", () => {
    describe("check", () => {
        it("should startFunc and send Log if check1 || check2 is false", () => {
            var check1 = sinon.stub(check1);
            check1.yields(false);
            var check2 = sinon.stub(check2);
            check2.yields(true);
            var startFunc = sinon.stub(startFunc);
            var sendLog = sinon.stub(sendLog);
            scripts.check();
            expect(sendLog).to.have.been.calledWith("started")
            expect(startFunc).to.have.been.calledOnce;
        })
    })
})

edit:

I have managed to get the test to work by making the function accessible. I'm still not sure this is the best method though

scripts.js

let check1 = function(){return true}
let check2 = function(){return true}
let startFunc = function(){console.log('checks Passed')}
let sendLog = function(message){console.log(message)}

module.exports.check1 = check1
module.exports.check2 = check2
module.exports.startFunc = startFunc
module.exports.sendLog = sendLog

module.exports.check=function(){

    console.log('check1: ', this.check1())
    console.log('check2: ', this.check2())

    if (!this.check1() || !this.check2()) {
        this.startFunc()
        this.sendLog("started")
    }
}

test.js:

"use strict";
var chai = require("chai");
var sinon = require("sinon");
var sinonChai = require("sinon-chai");
var expect = chai.expect;
chai.use(sinonChai);

var scripts = require('./scripts')

describe("scripts", () => {
    describe("check", () => {
        it("should startFunc and send Log if check1 || check2 is false", () => {
            var check1 = sinon.stub(scripts,'check1',() => {return true});
            var check2 = sinon.stub(scripts,'check2',()=> {return false});
            var startFunc = sinon.stub(scripts,'startFunc');
            var sendLog = sinon.stub(scripts,'sendLog');
            scripts.check();
            expect(sendLog).to.have.been.calledWith("started")
            expect(startFunc).to.have.been.calledOnce;
        })
    })
})
1

There are 1 answers

0
Radko Dinev On

I'd just expose the internal functions from the module (as you did in your edit above). However, I'd use some special notation, e.g. _check1 and _check2, or organization of code, e.g. module.exports.privateFunctions = { check1: check1, ... };, to denote that these are internal functions not part of the intended module interface.

Another approach, although I'm not sure whether that is a good practice, would be to extend the exported methods by adding the internal functions as their properties, e.g. module.exports.check.check1 = check1;. This way each exported function will have attached references to its internally used functions whose behavior can be stubbed. Moreover the interface is safe, i.e. even if you redefine check.check1 = function() { return 42; }; in some other part of the code, this would not affect check as it will invoke the original check1.