工厂方法参考混淆,以及编码它的指南

时间:2015-08-08 12:33:10

标签: javascript angularjs coding-style angularjs-service angularjs-factory

我有以下角度服务。

(function () {

    "use strict";

    angular.module("theModule")
      .factory("theService", theServiceFactory);

    function theServiceFactory() {

      return {
          theFn: theFn,
          theFailureFn: theFailureFn,
          theSuccessFn: theSuccessFn
      };

      function theFn() {
          angular.noop();
      }

      function theFailureFn() {
          theFn();
      }

      function theSuccessFn() {
        this.theFn();
      }

    }

}());

函数是单独定义的,它们的引用分配给工厂返回的对象。

我有以下茉莉花测试案例。

describe("The Service Test Specifications", function () {

    var theService;

    beforeEach(module('theModule'));

    beforeEach(inject(function(_theService_) {
        theService = _theService_;
    }));

    it("should call 'theFn' from 'theFailureFn'", function () {
        spyOn(theService, "theFn");
        theService.theFailureFn();
        expect(theService.theFn).toHaveBeenCalled();
    });

    it("should call 'theFn' from 'theSuccessFn'", function () {
        spyOn(theService, "theFn");
        theService.theSuccessFn();
        expect(theService.theFn).toHaveBeenCalled();
    });

});

测试用例should call 'theFn' from 'theFailure'正在失败,而should call 'theFn' from 'theSuccess'正在传递。

从源代码来看,似乎object's theFn指的是function theFn但实际上并非如此。它导致第一个测试用例失败。 (Q1)在什么阶段将不同的引用分配给object's theFn

theFnthis调用theSuccess时,第二个测试用例正在传递。但在这种情况下使用this是严格模式违规。我喜欢并关注John Papa's style guide所以我创建了factory并定义了它下面的所有函数。 (Q2)编写此类函数的更好方法是什么?

(Q3)如果theFailure写得正确,有没有办法在测试用例中检测到function theFn被调用?

Plunkr:http://plnkr.co/edit/PsQTZQlIgWI3OTMaYi7n

2 个答案:

答案 0 :(得分:3)

它实际上是从theFn()调用theFailureFn(),而不是从theFn()调用sucesssFn()。这是你测试的相反结果。

如你所见,

http://plnkr.co/edit/Tp5FtsL8DAjkcPO0m0ZV?p=preview

  console.log('theService.theFn BEFORE spyOn', theService.theFn);
  spyOn(theService, "theFn");
  console.log('theService.theFn AFTER spyOn', theService.theFn);

结果

  theService.theFn BEFORE spyOn theFn()
  theService.theFn AFTER  spyOn j$.createSpy.spy()

您的Jasmine spyOn(theService, "theFn");正在设置服务实例this.theFn,您的测试是否正在调用this.theFn。请记住,theService是哈希,而不是函数。

从这一行的输出中可以看出;

    console.log('caller theFailureFn', this, theFn, this.theFn)
    //OUTPUT
    caller theFailureFn Object {} theFn() j$.createSpy.spy()

theFnthis.theFn非常不同。 theFn是对象属性值,this.theFn是对象Hash的实例。

要回答你的问题,

(Q1)在什么阶段将不同的参考分配给对象theFn
{1}}按预期分配。 theFn makkes在您的情况下存在差异。

(Q2)编写此类函数的更好方法是什么?
要测试一个函数调用一个对象的函数,它应该返回一个函数,而不是一个哈希。

(Q3)如果故障写得正确,有没有办法在测试用例中检测到函数fn被调用? 与Q2相同的答案。

答案 1 :(得分:1)

请勿在{{1​​}}中使用this。 Factory只是作为函数执行,它只返回您明确指定为返回对象的内容。 Angular使用.factory()作为构造函数,使用.service()运算符执行,这就是您将使用new的位置。

这意味着您的this写得正确。

至于Q3,它可能会因为spyOn的实现方式而失败。

编辑:

正如我想的那样,它是theFailureFn()的实现。

spyOn包装了该功能,但在您的工厂中,您仍然在引用原始功能。尝试使用spyOn()