【问题标题】:Sinon - basic use with internal functionsSinon - 内部函数的基本使用
【发布时间】:2017-07-19 09:18:52
【问题描述】:

我无法获得使用 sinon 测试代码的基础知识。我有一个简单的模块,它调用两个内部函数并检查它们的结果。我打算使用存根来改变这些函数的输出,以测试模块如何响应。这可能吗?

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;
        })
    })
})

编辑:

通过使该功能可访问,我已设法使测试正常工作。我仍然不确定这是最好的方法

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;
        })
    })
})

【问题讨论】:

  • 我认为为了测试而公开私有方法是一种不好的模式。来自“实用单元测试”:一般来说,您不想为了测试而破坏任何封装(或者就像妈妈常说的,“不要暴露你的隐私!”)。大多数时候,您应该能够通过执行其公共方法来测试一个类。如果有重要的功能隐藏在私有或受保护的访问之后,这可能是一个警告信号,表明那里有另一个班级正在努力摆脱。

标签: javascript node.js mocha.js sinon stubs


【解决方案1】:

我只是从模块中公开内部功能(就像您在上面的编辑中所做的那样)。但是,我会使用一些特殊的符号,例如_check1_check2,或代码组织,例如module.exports.privateFunctions = { check1: check1, ... };,表示这些是内部函数,不是预期模块接口的一部分。

另一种方法,虽然我不确定这是否是一个好习惯,但通过添加内部函数作为它们的属性来扩展导出的方法,例如module.exports.check.check1 = check1;。这样,每个导出的函数都将附加对其内部使用的函数的引用,这些函数的行为可以被存根。此外,接口是安全的,即即使您在代码的其他部分重新定义check.check1 = function() { return 42; };,这也不会影响check,因为它会调用原始的check1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-24
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 2015-11-10
    相关资源
    最近更新 更多