Javascript 如何存根一段有问题的代码[单元测试]

Javascript 如何存根一段有问题的代码[单元测试],javascript,unit-testing,mocking,sinon,qunit,Javascript,Unit Testing,Mocking,Sinon,Qunit,对编写单元测试和更确切地说“模拟”的概念来说是新的。我有一个基本函数“addPercentSign”,如果用户输入在50-100之间,它会向用户输入添加一个百分比字符: addPercentSign: function (oEvent, control) { var inputVal = oEvent.getParameters().value; var inputNumber = parseFloat(inputVal); if (in

对编写单元测试和更确切地说“模拟”的概念来说是新的。我有一个基本函数“addPercentSign”,如果用户输入在50-100之间,它会向用户输入添加一个百分比字符:

    addPercentSign: function (oEvent, control) {
        var inputVal = oEvent.getParameters().value;
        var inputNumber = parseFloat(inputVal);

        if (inputNumber) {

            if (inputNumber < 50 || inputNumber > 100) {
                return null;
            } else {
                var finalVal = inputNumber.toFixed(1);
                var finalOutput = finalVal + "%";

//Error: cannot setValue of undefined. How can I 'stub' the line below?
                control.learningCurve.setValue(finalOutput);

                return finalOutput;
            };
        }
    }
问题

如何模拟setter,以便在没有DOM依赖项的情况下对该函数进行单元测试

control.learningCurve.setValue(finalOutput)
可作为测试的双重标准

本例使用的是sinon存根

sinon.stub(control.learningCurve, 'setValue').returns('value that you need');
编辑:


我不确定,因为我不是JS忍者,但我认为这不应该那么难

要使用的方法位于名为“learningCurve”的对象内,该对象位于“control”对象内

如果控件在格式化程序中,您就不能这样做:

formatter.control = {};
formatter.control.learningCurve = {};
formatter.control.learningCurve.setValue = function() {
    return something_to_return;
}   

assert.ok(formatter.addPercentSign(testEvent, viewControls) == '50.0%', "Percent Sign Added: Pass");

如果它不在formatter中,那就创建一个新的控件实例并替换上面的控件实例。

我发现单元测试的一个主要附加值是,它使您认识到可以在哪里重构代码。在您的例子中,有两个不同的关注点:追加%和修改DOM。通过将这两个关注点重构为各自的函数,您可以在不模仿任何东西的情况下对逻辑进行单元测试

//Formerly addPercentSign
inputChanged: function (oEvent, control) {
    var inputVal = oEvent.getParameters().value;
    var inputNumber = parseFloat(inputVal);
    var formattedNumber = addPercentSign(inputNumber);
    control.learningCurve.setValue(formattedNumber);
}

function addPercentSign(inputNumber) {
    if (inputNumber < 50 || inputNumber > 100) {
        return inputNumber;
    }
    var finalVal = inputNumber.toFixed(1);
    return finalVal + "%";
}
//以前添加百分比符号
输入更改:功能(oEvent,control){
var inputVal=oEvent.getParameters().value;
变量inputNumber=parseFloat(inputVal);
var formattedNumber=addPercentSign(inputNumber);
control.learningCurve.setValue(formattedNumber);
}
函数addPercentSign(inputNumber){
如果(输入编号<50 | |输入编号>100){
返回输入编号;
}
var finalVal=输入编号。固定(1);
返回最终值+“%”;
}

现在您可以轻松地测试addPercentSign。您也可以对inputChanged进行单元测试,但那只是对javascript框架进行单元测试。

谢谢,您能展示如何为上面的单元测试插入此代码吗?看起来第一个参数是control.learningCurve对象,而第二个是我想要的函数“stub”?是的,它将sinon.stub(对象,“方法”)作为参数传递。Sinon documents提供了更多关于如何使用存根的详细信息。谢谢,但我发现他们的文档非常难以理解,因为有些人只是在学习模拟、存根和间谍。。
formatter.control = {};
formatter.control.learningCurve = {};
formatter.control.learningCurve.setValue = function() {
    return something_to_return;
}   

assert.ok(formatter.addPercentSign(testEvent, viewControls) == '50.0%', "Percent Sign Added: Pass");
//Formerly addPercentSign
inputChanged: function (oEvent, control) {
    var inputVal = oEvent.getParameters().value;
    var inputNumber = parseFloat(inputVal);
    var formattedNumber = addPercentSign(inputNumber);
    control.learningCurve.setValue(formattedNumber);
}

function addPercentSign(inputNumber) {
    if (inputNumber < 50 || inputNumber > 100) {
        return inputNumber;
    }
    var finalVal = inputNumber.toFixed(1);
    return finalVal + "%";
}