简体   繁体   English

Angular 2+ Promise 单元测试

[英]Angular 2+ Promise Unit testing

Hi I'm trying to write jasmine unit test for following angular service.嗨,我正在尝试为以下角度服务编写 jasmine 单元测试。

However, I'm struggling how to write test for return promise value and wasn't able to find any elaborate resource how to write for these cases.但是,我正在努力如何编写返回承诺值的测试,并且无法找到任何详细的资源如何为这些情况编写。

Most struggle comes from not knowing how to test what has been called within the returned promise.大多数困难来自不知道如何测试返回的承诺中调用的内容。

For example, I want to test calling this.createMap() invokes this._mapResolver with map instance new google.maps.Map(el, mapOptions)例如,我想测试调用this.createMap()调用this._mapResolver与地图实例new google.maps.Map(el, mapOptions)

Could an Angular 2+ guru help me understand writing spec for promises? Angular 2+ 大师可以帮助我理解 Promise 的编写规范吗? or references to learn from?或参考学习?

declare let google: any;

/**
 * Wrapper class that handles the communication with the Google Maps Javascript
 * API v3
 */
@Injectable()
export class GoogleMapsAPIWrapper {
  private _map: Promise<mapTypes.GoogleMap>;
  private _mapResolver: (value?: mapTypes.GoogleMap) => void;

  constructor(private _loader: MapsAPILoader, private _zone: NgZone) {
    this._map =
      new Promise<mapTypes.GoogleMap>((resolve: () => void) => { this._mapResolver = resolve; });
  }

  createMap(el: HTMLElement, mapOptions: mapTypes.MapOptions): Promise<void> {
    return this._loader.load().then(() => {
      const map = new google.maps.Map(el, mapOptions);
      this._mapResolver(<mapTypes.GoogleMap>map);
      return;
    });
  }

  setMapOptions(options: mapTypes.MapOptions) {
    this._map.then((m: mapTypes.GoogleMap) => { m.setOptions(options); });
  }
}

Solution suggested by @ArmenVardanyan @ArmenVardanyan 建议的解决方案

describe('Service: GoogleMapsAPIWrapper', () => {

  const loaderServiceStub = {
    load: () => Promise.resolve()
  };

  let service;


  beforeEach(async(() => {
    TestBed.configureTestingModule({
      providers: [
        GoogleMapsAPIWrapper,
        {provide: MapsAPILoader, useValue: loaderServiceStub}
      ]
    });
  }));

  beforeEach(async(inject([GoogleMapsAPIWrapper], (_service: GoogleMapsAPIWrapper) => {
    service = _service;
  })));


  it('should be created',() => {
    expect(service).toBeTruthy();
  });

  it('should be call _mapResolver with specified arguments', async(() => {
    const elem = document.createElement('div');
    const spyOnCreateMap = spyOn(service, '_mapResolver');
    service.createMap(elem, {})
      .then(() => {
        expect(spyOnCreateMap).toHaveBeenCalled();
        expect(spyOnCreateMap).toHaveBeenCalledWith(new google.maps.Map(elem, {}));
      });
  }));

});

I don't remember how to correctly inject NgZone int tests, but as I see it is irrelevant to your question.我不记得如何正确注入 NgZone int 测试,但据我所知,这与您的问题无关。 So You just have to mock the MapsAPILoader service and test the _mapResolver .所以你只需要模拟 MapsAPILoader 服务并测试_mapResolver

 const loaderServiceStub = { load: () => Promise.resolve() }; describe('GoogleMapsAPIWrapper', () => { beforeEach(() => { TestBed.configureTestingModule({ providers: [ GoogleMapsAPIWrapper, {provide: MapsAPILoader, useValue: loaderServiceStub} ] }); }); it('should be created', inject([GoogleMapsAPIWrapper], (service: GoogleMapsAPIWrapper) => { expect(service).toBeTruthy(); })); it('should be call _mapResolver with specified arguments', inject([GoogleMapsAPIWrapper], (service: GoogleMapsAPIWrapper) => { const spyOnCreateMap = spyOn(service, '_mapResolver'); service.createMap(new HTMLDivElement(), {/*options */}); expect(spyOnCreateMap).toHaveBeenCalled(); })); });

So you basically mock the loader service to just return a resolved Promise when load is called, and then check if _mapResolver has been called.因此,您基本上模拟加载器服务,以便在调用load时返回一个已解决的 Promise,然后检查_mapResolver是否已被调用。 But you cannot check if the arguments provided were correct, because of this lines:但是由于以下几行,您无法检查提供的参数是否正确:

const map = new google.maps.Map(el, mapOptions);
this._mapResolver(<mapTypes.GoogleMap>map);

There is a map being created inside the callback passed to the then method, but you cannot know what that object is going to be.在传递给then方法的回调中创建了一个映射,但您无法知道该对象将是什么。 You can try你可以试试

expect(spyOnCreateMap).toHaveBeenCalledWith(new google.maps.Map(el, mapOptions));

but I'm almost sure it is not going to work.但我几乎可以肯定它不会起作用。 The same issue goes with the second Test you want to write: the _map promise will return an object which has a setOptions method, but you don't really know what that object is going to be.您要编写的第二个测试也存在同样的问题: _map承诺将返回一个具有setOptions方法的对象,但您并不真正知道该对象将是什么。 Or else you will have to mock that Promise either and then make sure your mocked setOptions method has been called.否则,您将不得不模拟该 Promise,然后确保您模拟的setOptions方法已被调用。

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

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