工厂方法引用混淆,并指导其编码

Factory method reference confusion, and guideline to code it

本文关键字:编码 方法 引用 工厂      更新时间:2023-09-26

我有以下angular服务:

(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在哪个阶段被分配不同的引用?

第二个测试用例是通过theFntheSuccess内部的this调用。但是在这种情况下使用this是严格违反模式的。我喜欢并遵循John Papa的风格指南,所以我创建了factory并定义了它下面的所有函数。(Q2)如何更好地编写这样的函数?

(Q3)如果theFailure写得正确,是否有任何方法可以在测试用例中检测function theFn被调用?


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

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

如你所见,

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

预览
  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
theFn按您的期望分配。spyOn对你的情况很重要。

(Q2)如何更好地编写这样的函数?
要测试一个函数调用一个对象的函数,它应该返回一个函数,而不是一个散列。

(Q3)如果failure写得正确,是否有任何方法可以在测试用例中检测函数theFn被调用?和Q2一样。

不要在.factory()中使用this。Factory只是作为函数执行它只是返回你显式指定的返回对象。Angular使用.service()作为构造函数,它使用new运算符执行,在这里你将使用this

这意味着你的theFailureFn()是正确的。

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

编辑:

如我所料,这是spyOn()的实现。

spyOn包装了函数,但是在你的工厂中你仍然引用原始函数。尝试使用expect(this.theFn).toHaveBeenCalled();

相关文章: