如何存储有问题的代码[单元测试]

时间:2016-12-07 03:07:15

标签: javascript unit-testing mocking sinon qunit

新编写单元测试和'嘲笑'的概念更准确。我有一个基本功能'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;
            };
        }
    }

问题

我面临的问题是当我为这个函数编写单元测试时,我无法测试返回值(finalOutput),因为它上面的行返回错误,因为它依赖于DOM元素(control.learningCurve)来设定一个值。由于这是一个单元测试,我必须将此函数与任何依赖项隔离开来。

因此,我需要'模拟''setValue'调用。我认为创建一个存根会有意义,但我不确定如何?

以下是我要测试上述函数的单元测试代码(addPercentSign):

function (formatter, viewControls) {
    "use strict";

    var testEvent = {
        getParameters : function() {
                return {value : 50}
        }
    }

    QUnit.module("Formatter Functions");
    QUnit.test("Add Percent Sign", function (assert) {

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

    });
}

问题

如何模拟setter以便我可以在没有DOM依赖性的情况下对此函数进行单元测试?:

control.learningCurve.setValue(finalOutput)

3 个答案:

答案 0 :(得分:1)

Sinon可以用作测试双倍。

这个例子是使用sinon stub。

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

编辑:

function (formatter, viewControls) {
"use strict";

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

    var testEvent = {
        getParameters : function() {
                return {value : 50}
        }
    }

    QUnit.module("Formatter Functions");
    QUnit.test("Add Percent Sign", function (assert) {

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

    });
}

答案 1 :(得分:0)

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

您要使用的方法是在名称为&#39; learningCurve&#39;内部控制&#39;对象

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

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

如果它不在格式化程序中,那么通过创建一个新的控件实例并替换上面的内容来实现格式化。

答案 2 :(得分:0)

我发现单元测试的主要附加值之一就是它可以让你意识到你的代码可以被重构的地方。在您的情况下,有两个不同的问题:附加%和修改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 + "%";
}

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