简体   繁体   English

如何使用spyOn测试Promise.all的功能

[英]How to test then function of Promise.all with spyOn

I'm a newbie to coding, so please ask if more information is necessary. 我是编码的新手,因此请询问是否需要更多信息。

I want to test a then-block inside a Promise.all with spyOn, but the function get never called. 我想用spyOn测试Promise.all内部的一个then块,但是永远不会调用该函数。

public foo(): void {
    const names = this.getNames();

    Promise.all(
      names.map(name =>
        this.nameService.doSomething( //some params )
      )
    )
      .then(result => this.controller.ok(names))
      .catch(error => {
        //do something
      });
  }

This is the test 这是测试

it('should call controller.ok when name is set', () => {
    spyOn(nameService, 'doSomething').and.returnValue(Promise.resolve());
    spyOn(controller, 'ok');

    service.foo();

  expect(nameService.doSomething).toHaveBeenCalledWith({
      //some params
    });
  expect(controller.ok).toHaveBeenCalled(); //fails because never called
  });

I've debugged the code and the doSomething get called even with the right params, the code also reaches the then-block. 我已经调试了代码,即使使用正确的参数也调用了doSomething,代码也到达了then块。 But the test says, it never gets called, so somewhere in there the code breaks and I don't know why? 但是测试说,它永远不会被调用,所以代码在某处中断了,我不知道为什么?

The catch-block is not called. catch块不被调用。

Promises representing the eventual completion or failure of an asynchronous operation. 表示异步操作最终完成或失败的承诺。 Within your test, when checking if controller.ok has been called, the Promise returned by Promise.all of method foo was not resolved yet. 在您的测试,检查是否在controller.ok被调用, Promise返回由Promise.all方法foo尚未解决。 Therefore you need some sort of synchronization. 因此,您需要某种同步。

One possible solution could look as follows. 一种可能的解决方案如下所示。

it('should call controller.ok when name is set', () => {
    const promises: Promise<any>[] = [];
    spyOn(nameService, 'doSomething').and.callFake(n => {
        const promise = Promise.resolve();
        promises.push(promise);
        return promise;
    });
    spyOn(controller, 'ok');

    service.foo();

    Promise.all(promises)
         .then(r => expect(controller.ok).toHaveBeenCalled());
});

The same can be achieved by using fakeAsync and tick from @angular/core/testing . 通过使用fakeAsync@angular/core/testing tick可以实现相同的目的。

it('should call controller.ok when name is set', fakeAsync(() => {
    spyOn(nameService, 'doSomething').and.returnValue(Promise.resolve());
    spyOn(controller, 'ok');

    service.foo();
    tick();

    expect(controller.ok).toHaveBeenCalled();
}));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM