用Jasmine窥探整个实例的任何方法

时间:2012-01-24 21:12:24

标签: javascript unit-testing jasmine

我有一个复杂的javascript类,它有很多函数,如果在生产环境之外调用它们,很多函数会抛出异常。我需要在我的测试中将此类的模拟实例传递给另一个类的构造函数,但是我不希望实际调用任何复杂的类函数。我想做的是拥有一个假对象,它具有复杂类的所有功能和属性,但是所有的功能都只是茉莉花间谍,什么都不做。

基本上我希望能够做到

var fakeComplexClass = createFakeObject(ComplexClass);

var testInstanceOfSimpleClass = new SimpleClass( fakeComplexClass);

请确保如果testInstanceOfSimpleClass调用任何fakeComplexClass函数,它们将成为间谍,从而不会导致我的测试崩溃。

我可以做类似

的事情
var fakeComplexClass = { function1() {};, function2() {}; ... } 

但是有很多函数我需要测试一些不同的复杂类,所以只需要一个简单的方法来基本监视类中的每个函数就是我需要的。\

Jasmine确实有createSpyObj,但它要求你传递一系列函数。如果我碰巧在复杂类中添加或删除函数,我不想在我的测试中维护该数组,所以我想要一些可以监视每个函数的东西。

提前致谢。

2 个答案:

答案 0 :(得分:1)

我创建了一个小型lib,它与jasmine-node一起使用。

用法:

    var MyClass = function (param) {
        this.initialize(param);
    };
    MyClass.prototype.initialize = function (param) {
        if (param != "expectedParam")
            throw new TypeError();
    };

    var mock1 = jasmine.createStub(MyClass, ["*"]);
    expect(mock1.constructor).toHaveBeenCalled();
    expect(mock1.initialize).not.toHaveBeenCalled();

    var mock2 = jasmine.createStub(MyClass, ["initialize"], ["expectedParam"]);
    expect(mock2.initialize).toHaveBeenCalled();
    mock2.initialize.andCallThrough();
    expect(mock2.initialize).toThrow(new TypeError());

LIB:

jasmine.createStub = function (cls, methods, args) {
    if (!(cls instanceof Function))
        throw new TypeError("Invalid class param.");

    var mockClass = function () {
        this.constructor.apply(this, args || []);
    };

    mockClass.prototype = Object.create(cls.prototype);
    mockClass.prototype.constructor = cls;

    var wrap = function (method) {
        if (!mockClass.prototype[method] instanceof Function)
            throw new TypeError("Cannot mock " + method + " it's not a function.");
        jasmine.getEnv().currentSpec.spyOn(mockClass.prototype, method);
    };

    if (methods) {
        if (!(methods instanceof Array))
            methods = [methods];
        if (methods.length == 1 && methods[0] == "*")
            for (var property in mockClass.prototype) {
                if (mockClass.prototype[property] instanceof Function)
                    wrap(property);
            }
        else
            for (var i = 0; i < methods.length; ++i) {
                var method = methods[i];
                wrap(method);
            }
    }

    return new mockClass();
};

我认为这行不适用于浏览器中的jasmine,但没有测试它:

jasmine.getEnv().currentSpec.spyOn(mockClass.prototype, method);

不知怎的,我的jasmine-node没有jasmine.spyOn方法......

答案 1 :(得分:0)

看看SinonJS,它会让你stub一个完整的对象:

  

var stub = sinon.stub(obj);   存根所有对象的方法。