Search code examples
javascripttestingjasminespy

How to use Jasmine spies on an object created inside another method?


Given the following code snippet, how would you create a Jasmine spyOn test to confirm that doSomething gets called when you run MyFunction?

function MyFunction() {
    var foo = new MyCoolObject();
    foo.doSomething();
};

Here's what my test looks like. Unfortunately, I get an error when the spyOn call is evaluated:

describe("MyFunction", function () {
    it("calls doSomething", function () {

        spyOn(MyCoolObject, "doSomething");
        MyFunction();
        expect(MyCoolObject.doSomething).toHaveBeenCalled();

    });
});

Jasmine doesn't appear to recognize the doSomething method at that point. Any suggestions?


Solution

  • When you call new MyCoolObject() you invoke the MyCoolObject function and get a new object with the related prototype. This means that when you spyOn(MyCoolObject, "doSomething") you're not setting up a spy on the object returned by the new call, but on a possible doSomething function on the MyCoolObject function itself.

    You should be able to do something like:

    it("calls doSomething", function() {
      var originalConstructor = MyCoolObject,
          spiedObj;
      spyOn(window, 'MyCoolObject').and.callFake(function() {
        spiedObj = new originalConstructor();
        spyOn(spiedObj, 'doSomething');
        return spiedObj;
      });
      MyFunction();
      expect(spiedObj.doSomething).toHaveBeenCalled();
    });