为什么茉莉花间谍没有通过引用解析函数对象?

时间:2016-03-25 15:31:00

标签: javascript angularjs jasmine

我有以下简单的服务

app.factory('Shoes', function() {
    function a() {return 12;}
    function b() {return a();}

    return {
      a: a,
      b: b
    }
  })

我想测试在调用方法a时是否正在调用方法b。我的测试看起来像这样:

describe('Testing a Shoes service', function() {
  var service;

  beforeEach(module('plunker'));

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

  it('.b should call .a', function() {
    spyOn(service, 'a');
    service.b();
    expect(service.a).toHaveBeenCalled();
  })

});

但测试失败了。相关的plunker是here。我已经知道如何从those answers解决问题。还有一个未解决的问题:

为什么原始功能对象没有被解析?

我认为系统的工作方式是这样的(假设spyies用额外的逻辑来装饰函数)

当我致电service.a时我没有间谍时,它被解决为:

A) service.a -> a()

当我创建一个间谍时,它会修饰函数

B) spy -> service.a => service.a*()

但是service.a基本上是原始a()的引用,所以我们最终应该为已解析的函数对象设置一个间谍集:

A + B => spy -> service.a -> a => a*()

1 个答案:

答案 0 :(得分:3)

致电spyOn(service, 'a')后,service.a不再是您在函数中定义的a - 它是间谍功能。该间谍功能恰好调用a,但不是a ;它具有不同的身份,是一种不同的功能。

但是,设置a service属性不会更改您在function a内声明的app.factory。您只是更改了service,因此其a属性不再引用您的原始a。相比之下,您的b函数永远不会更改其对原始a的引用。它从最初声明aapp.factory的本地a范围直接获得bservice替换其原始a与间谍的事实不会影响ba()的调用,因为它不会引用service.a }。