The spyOn() function can only replace the properties of an object, so the only thing you can do is keep an eye on the prototype. Now, if you follow the prototype of a real class, this will interfere with other tests, so you should use prototype inheritance.
You can do something like this:
var mockClass = function (Subject) { var Surrogate = function () { Surrogate.prototype.constructor.apply(this, arguments); }; Surrogate.prototype = Object.create(Subject.prototype); Surrogate.prototype.constructor = Subject; return Surrogate; };
Some tests:
var My = function (a) { this.init(a); }; My.prototype = { init: function (a) { this.setA(a); }, setA: function (a) { this.a = a; } }; var Mock = mockClass(My); spyOn(Mock.prototype, "constructor").andCallThrough(); spyOn(Mock.prototype, "init"); var m = new Mock(1); expect(Mock.prototype.init).toBe(m.init); expect(My.prototype.init).not.toBe(m.init); expect(m.constructor).toHaveBeenCalledWith(1); expect(m.init).toHaveBeenCalledWith(1); expect(ma).toBeUndefined(); m.setA(1); expect(ma).toBe(1); spyOn(Mock.prototype, "setA").andCallFake(function (a) { this.a = a + 1; }); m.setA(1); expect(m.setA).toHaveBeenCalledWith(1); expect(ma).toBe(2);
You cannot keep an eye on constructor if your code uses type checking based on x.constructor . But I think this can only happen with the help of integration tests and poorly designed codes ...
source share