如何在没有eval的情况下编写这个JavaScript代码(QUnit mocking)?

时间:2012-01-02 22:39:04

标签: javascript mocking eval qunit

我一直在尝试使用QUnit测试,并且正在寻找一种用mocks覆盖函数的好方法,以便能够进行更多的原子测试。对于特定情况,有很好的解决方案,例如覆盖$ .ajax(Simple jQuery (1.5+) AJAX Mocking),但我正在寻找更通用的方法,并想出了这个:

// Constructor for overrides.
function overrides(overrides) {
    this.overrides = overrides;
}

// Implementation for overrides.
overrides.prototype = {
    set: function () {
        var functions = {};
        $.each(this.overrides, function (key, value) {
            eval("functions['" + key + "'] = " + key + ";");
            eval(key + " = value;");
        });
        this.functions = functions;
    },

    reset: function () {
        var functions = this.functions;
        $.each(this.overrides, function (key, _) {
            eval(key + " = functions['" + key + "'];");
        });
    }
}

然后可以使用:

module("Comments", {
    setup: function () {
        this.overrides = new overrides({ "$.ajax": function (url, options) {
            alert("ajax: " + url + ', ' + options);
        }
        });

        this.overrides.set();
    },
    teardown: function () {
        this.overrides.reset();
    }
});

现在,一切似乎都运行正常,虽然这可能不是eval()的最坏使用,但我想知道这是否确实可以在不使用eval()的情况下编写?我在这里阅读了一堆其他的eval()问题并尝试了各种选项,比如使用window []访问覆盖,但这对$ .ajax情况不起作用(例如window ['$']。ajax有效但不是窗口['$ .ajax'])。

也许我也在努力思考,eval()可以在这里安全地使用,或者对于函数覆盖有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

为什么不能将对象视为对象?

functions[key] = key;

var arr = key.split('.');
var obj = window;

for (var i = 0; i < arr.length; i++){
  if (obj) obj = obj[arr[i]];
}

obj = value;

答案 1 :(得分:1)

据我所知,唯一的方法是分别提供对象和属性名称。本地函数(例如Object.defineProperty)也是这种情况,它将对象作为一个参数,将属性名称作为字符串作为另一个参数。

// overwrite properties inside `$`

new overrides($, {"ajax": function (url, options) {
    alert("ajax: " + url + ', ' + options);
}});

这样的事情:

function overrides(obj, overrides) {
    this.obj = obj;
    this.overrides = overrides;
}

set: function () {
    var functions = {};
    var inst = this;

    $.each(this.overrides, function (key, value) {
        functions[key] = inst.obj[key]; // old function
        inst.obj[key] = value; // overwrite function
    });

    this.functions = functions;
},

它有效,因为inst.obj$引用相同的对象 - inst.obj上的更改属性也会修改$

相关问题