如何监视调用另一个返回承诺的服务的服务函数 - 打字稿

Posted

技术标签:

【中文标题】如何监视调用另一个返回承诺的服务的服务函数 - 打字稿【英文标题】:How to spy on a service function that calls another service which returns a promise - typescript 【发布时间】:2016-05-02 07:47:36 【问题描述】:

家长服务:

module proj.Stuff 
  export class ParentService 
    //...properties, constructor, etc

    public refreshStuff(id: number) 
      this.childService
        .getStuff(id)
        .then((response) => this.stuff = response);
      
   

儿童服务:

module proj.Stuff 
  export class ChildService
    //... properties, constructor, etc

    public getStuff(id: number) 

      var request: IPromise<any> = this.$http.get(
      ChildService.apiUrlBase + "getStuff/" + id
      );

      return request
       .then(response => 
         return response.data.value;
      , response => 
        this.$log.error("unable to get...");
      );
    
  

父服务的测试:

describe("ParentService", () => 

  // (property declarations omitted for brevity)

  beforeEach(angular.mock.module(["$provide", ($provide) => 

    var obj = 
      getStuff: (id: number) => 
        functionCalled = true;
        return 
          then: (callback) => 
            return callback(["result"]);
          
        ;
      
    ;

    $provide.value("ChildService", obj);
  ]));

  beforeEach(mock.inject((_$http_, _$log_, _$q_, _$httpBackend_, _$rootScope_, _ChildService_) => 
    cService = _ChildService_;
    pService = new ParentService(cbService);
  ));

  it("can be created", () => 
    expect(pService).toBeDefined();
    expect(pService).not.toBeNull();
  );

  it("can refresh stuff", () => 
    pService.refreshStuff(1);
    expect(pService.stuff).toEqual(["result"]);
    expect(functionCalled).toBeTruthy();

    // ***** what I want to do: *****
    // expect(cService.getStuff).toHaveBeenCalled();
  );
);

我想知道如何监视 cService.getStuff 而不是使用“functionCalled”布尔值?

当我试图监视它时,它抱怨 .then 没有定义 - 例如在第一个 beforeEach 中,如果我尝试 spyOn(obj, "getStuff") 它不喜欢它。

测试按原样通过,但宁愿 spyOn 而不是使用布尔值。

【问题讨论】:

【参考方案1】:

then 方法模拟很少被证明是合理的,Angular DI 允许使用未模拟的 Promise 并专注于单元测试。

  beforeEach(angular.mock.module(["$provide", ($provide) => 
    // allows to inject $q, while $provide.value doesn't
    $provide.factory("ChildService", ($q) => (
      // fresh promise on every call
      getStuff: jasmine.createSpy('getStuff').and.callFake(() => $q.when('result'))
    ));
  ]));

使用Jasmine promise matchers 效果最好,否则应涉及常规承诺规范:

var result;
...then((_result) =>  result = _result; )
$rootScope.$digest();
expect(result)...

【讨论】:

实现我得到 'undefined' 不是一个对象(评估 'jasmine.createSpy("getStuff").and.callFake')... 似乎是执行 .and 时反复出现的问题。 returnValue 或 and.callThrough 在这些上,它说 undefined @mapleafman 检查控制台的堆栈跟踪和其他错误。间谍本身没有问题,plnkr.co/edit/SXV9Q3Xr4AwyqGbpbv78?p=preview

以上是关于如何监视调用另一个返回承诺的服务的服务函数 - 打字稿的主要内容,如果未能解决你的问题,请参考以下文章

如何创建从回调函数返回承诺的函数[重复]

.catch() 甚至通过 fetch() 从另一个承诺中捕获所有错误

如何执行带有承诺的函数并通过 API 调用多次检查其值并使用该值执行另一个函数?

如何模拟在 AngularJS Jasmine 单元测试中返回承诺的服务?

链接承诺,或一个承诺触发另一个

我的返回值函数失败 - 我认为与承诺相关