【问题标题】:Jasmine: Real function being called after spyOn with function referenceJasmine:在带有函数引用的 spyOn 之后调用真正的函数
【发布时间】:2016-07-07 17:52:41
【问题描述】:

我有一个角度服务。在这个服务中,我有一个带有函数的对象,它引用了服务上的另一个函数。 (代码如下)

我想使用 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 / Angular / Jasmine 的哪一部分?

【问题讨论】:

    标签: javascript angularjs unit-testing jasmine spy


    【解决方案1】:

    spyOn 通过将对象属性的值替换为不同的值来进行操作。当您执行spyOn(service, "fooFunction"); 时,您正在执行类似的操作

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

    请注意,这不会修改值service.fooFunction。它实际上修改了service——也就是说,service 的属性之一现在是一个完全不同的函数。此替换只会影响servicefooFunction 属性。如果您没有访问 service 的属性,那么您肯定不会调用 spy 函数。

    因此,让我们将这些知识应用到您的案例中。在您的测试中,您正在访问service.bar 的属性。虽然service.bar.barFunctionservice.fooFunction 最初是相同的值,但servicefooFunction 属性已被间谍替换,而(非常重要的是)service.bar 的任何属性都没有被spyOn 改变。当您调用service.bar.barFunction() 时,您直接调用了真正的函数,并且与居住在servicefooFunction 属性上的间谍没有任何联系。

    相比之下,当您将barFunction: function() { return self.fooFunction(); } 作为匿名函数执行时,您实际上正在访问service 上的间谍属性值,因为这里的self 恰好是service,所以self.fooFunctionservice.fooFunction,这是保存间谍替换值的属性。

    【讨论】:

    • 我认为是这样的。无论如何要测试这些?
    • @Mistrog 您监视的是属性,而不是函数值,因此您必须监视要调用的确切对象/属性。或者,使用您的第二个示例中存在的模式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多