2016-07-07 3 views
1

У меня есть угловое обслуживание. Внутри этой службы у меня есть объект с функцией, которая ссылается на другую функцию службы. (Код ниже)Жасмин: Реальная функция вызывается после spyOn с ссылкой на функцию

Я хочу использовать Jasmine (1.3), чтобы шпионить за моей службой, чтобы убедиться, что при вызове функции объекта она фактически вызывает реальную функцию.

Моя проблема: после вызова функции spyOn по-прежнему вызывается реальная функция.

FooService.js

angular.module('foo').service("FooService", function() { 
    var self = this; 

    this.fooFunction = function() { 
     console.log("Foo function is being called"); 
    } 

    this.bar = { 
     barFunction : self.fooFunction 
    } 
}); 

FooService-spec.js

describe("Testing FooService", function() { 
    var service; 

    beforeEach(inject(function(_FooService_) { 
     service = _FooService_; 
    })); 

    describe("Test bar object", function() { 
     it("should call fooFunction when bar.barFunction is called", function() { 
      spyOn(service, "fooFunction"); 
      service.bar.barFunction(); 
      expect(service.fooFunction).toHaveBeenCalled(); 
     }); 
    }); 
}); 

Я обнаружил, что если я изменю FooServce.js к следующему, все это работает, хотя:

FooService - Работающий

angular.module('foo').service("FooService", function() { 
    var self = this; 

    this.fooFunction = function() { 
     console.log("Real function is being called"); 
    } 

    this.bar = { 
     barFunction : function() { 
      return self.fooFunction(); 
     } 
    } 
}); 

Какая часть JavaScript/Угловая/Жасмин я не понимаю в первом примере?

ответ

0

spyOn работает, заменяя значение свойства объекта на другое значение. Когда вы делаете spyOn(service, "fooFunction"); вы делаете что-то вроде

var realFunc = service.fooFunction; 
service.fooFunction = function() { 
    doSpyStuff(); 
    return realFunc.apply(this, arguments); 
} 

Обратите внимание, что это не изменяет значение service.fooFunction. Фактически он изменяет service, а именно, одно из свойств service - теперь совершенно другая функция. Эта замена повлияет только на свойство fooFunctionservice. Если вы не получаете доступ к свойству service, вы, конечно, не на пути к вызову функции шпиона.

Итак, давайте применим это знание к вашему делу. В вашем тесте вы получаете доступ к свойству service.bar. В то время как service.bar.barFunction и service.fooFunction были первоначально того же значения, service имел свое имущество fooFunction, замененное шпионом, в то время как (очень важно) service.bar не имеет никаких свойств, измененных spyOn. Когда вы вызываете service.bar.barFunction(), вы напрямую вызываете реальную функцию и не имеете никакого подключения к шпиону, который живет на servicefooFunction.

В противоположность этому, когда вы делаете barFunction: function() { return self.fooFunction(); } как анонимную функцию, вы на самом деле являются доступа к значению шпионский собственности на service, потому что здесь self случается service, так self.fooFunction является service.fooFunction, который является собственностью, которая держит шпиона восстановительная стоимость.

+0

Я понял, что это что-то такое. В любом случае, чтобы проверить их? – Mistrog

+0

@Mistrog Вы проверяете свойства, а не на значения функций, поэтому вам нужно будет отслеживать точный объект/свойство, которое вы хотите вызвать. Кроме того, используйте шаблон, присутствующий в вашем втором примере, который работает. – apsillers

Смежные вопросы