I have a complex javascript class that has many functions, many of which will throw exceptions if they are called outside of a production environment. I need to pass mock instances of this class to the constructor of another class in my tests, however I do not want any of the complex classes functions to actually be called. What I would like to do is have a fake object that has all the functions and properties of the complex class, but for all the functions to just be jasmine spies that do nothing.
Basically I want to be able to do
var fakeComplexClass = createFakeObject(ComplexClass);
var testInstanceOfSimpleClass = new SimpleClass( fakeComplexClass);
And be sure that if testInstanceOfSimpleClass
calls any of the fakeComplexClass
functions they will be spies and thus not crash my tests.
I could do something like
var fakeComplexClass = { function1() {};, function2() {}; ... }
but there are many functions and I have a few different complex classes I need to test so just an easy way to basically spy on every single function in a class is what I need.\
Jasmine does have createSpyObj but it requires that you pass it an array of functions. I don't want to have to maintain that array in my tests if I happen to add or delete functions from the complex class so I'd like something that can just spy on every function that is there.
Thanks in advance.
I created a small lib, which works with jasmine-node.
usage:
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();
};
I think this row wont work with jasmine in browser, but did not test it:
jasmine.getEnv().currentSpec.spyOn(mockClass.prototype, method);
Somehow my jasmine-node does not have a jasmine.spyOn method...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With