首页 > 解决方案 > 用 jasmine spy 测试 cdk 覆盖

问题描述

和测试mat-dialog类似,测试cdk覆盖有什么好方法?

MatDialog 服务单元测试 Angular 6 错误

服务调用示例:

openNotifications(origin: HTMLElement) {
    this.refreshNotifications()
      .subscribe();
    const overlayRef = this.overlay.create({
      positionStrategy: this.overlay.position().flexibleConnectedTo(origin).withPositions([
        {
          originX: 'center',
          originY: 'bottom',
          overlayX: 'center',
          overlayY: 'top',
        }
      ]),
      hasBackdrop: true,
    });
    const portal = new ComponentPortal(NotificationsDropdownComponent);
    overlayRef.attach(portal);
    overlayRef.backdropClick().subscribe(() => {
      overlayRef.detach();
      this.refreshNotificationCount().subscribe();
    });
  }

标签: angularjasmineangular-materialkarma-jasmineangular-cdk

解决方案


我创建了一个 overlaySpyHelper,本质上我们仍然使用 Overlay 服务,但是我们窥探了 create 方法并返回了一个 mock overlayRef

import {TestBed} from '@angular/core/testing';

import {NotificationsService} from './notifications.service';
import {UserNotificationsService} from '../swag-api/services';
import {Overlay, OverlayModule} from '@angular/cdk/overlay';
import {of} from 'rxjs';
import {UserNotificationsResponse} from '../swag-api/models';




describe('Given NotificationsService', () => {
  let notificationsService: NotificationsService;
  let userNotificationsServiceSpy: jasmine.SpyObj<UserNotificationsService>;
  let overlayService: Overlay;

  beforeEach(() => {
    const spy1 = jasmine.createSpyObj('UserNotificationsService',
      {
        UserNotificationsGetCount: of({count: 5}),
        UserNotificationsGetAll: of(getMockNotifications())
      });
    TestBed.configureTestingModule({
      imports: [
        OverlayModule,
      ],
      providers: [
        NotificationsService,
        {provide: UserNotificationsService, useValue: spy1},
      ],
    });

    notificationsService = TestBed.get(NotificationsService);
    userNotificationsServiceSpy = TestBed.get(UserNotificationsService);
    overlayService = TestBed.get(Overlay);
  });

  fdescribe('When openNotifications', () => {
    let createSpy;
    let overlayRefSpyObj;
    let simulateClickBackdropEvent;

    beforeEach(() => {
      ({createSpy, overlayRefSpyObj, simulateClickBackdropEvent} = overlaySpyHelper(overlayService));
      expect(userNotificationsServiceSpy.UserNotificationsGetAll.calls.count()).toBe(0);
      notificationsService.openNotifications(null);
    });

    it('overlay created', () => {
      expect(createSpy).toHaveBeenCalled();
    });

    it('then notifications refreshed', () => {
      expect(userNotificationsServiceSpy.UserNotificationsGetAll.calls.count()).toBe(1);
    });

    it('then overlay opened', () => {
      // overlayRef.attach();
      expect(overlayRefSpyObj.attach).toHaveBeenCalled();
      expect(overlayRefSpyObj.backdropClick().subscribe).toHaveBeenCalled();
      expect(overlayRefSpyObj.detach).not.toHaveBeenCalled();
    });

    it('When backdrop clicked, close overlay and refresh count', () => {
      expect(userNotificationsServiceSpy.UserNotificationsGetCount.calls.count()).toBe(0);
      simulateClickBackdropEvent.callback();
      expect(overlayRefSpyObj.detach).toHaveBeenCalled();
      expect(userNotificationsServiceSpy.UserNotificationsGetCount.calls.count()).toBe(1);
    });

  });
});

function overlaySpyHelper(overlayService) {
  const simulateClickBackdropEvent = {callback: null};
  const overlayRefSpyObj = jasmine.createSpyObj({
    attach: null,
    backdropClick: jasmine.createSpyObj({subscribe: null}),
    detach: null,
  });
  const createSpy = spyOn(overlayService, 'create').and.returnValue(overlayRefSpyObj);
  overlayRefSpyObj.backdropClick().subscribe.and.callFake((cb) => {
    simulateClickBackdropEvent.callback = cb;
  });
  return {createSpy, overlayRefSpyObj, simulateClickBackdropEvent};
}

推荐阅读