Тестовое покрытие не покрывает тестовое письмо - PullRequest
0 голосов
/ 20 января 2020

Я пишу тест с использованием Жасмин для приложения Angular 8. Я написал тест для подтверждения диалога. У меня есть три условия для проверки при отображении диалогового окна подтверждения. Сбросить, отклонить и одобрить. В тот момент, когда я запускаю npm тестовое покрытие для тестового покрытия, его выделение остальной части кода ниже не рассматривается. Я думал, что мой тест («должен вызвать диалог подтверждения отказа») должен был покрыть это. Я не уверен, почему тесты не охватывают немного? Может ли кто-нибудь помочь

if (type === 'Approve') {
  this.confirmationDialog.show(this.approvalMessage, type, () => this.confirm(type));
} else if (type === 'Reset') {
  this.confirmationDialog.show(this.resetMessage, type, () => this.confirm(type));
} else if (type === 'Reject') {
  this.confirmationDialog.show(this.rejectMessage, type, () => this.confirm(type));
}

Код компонента

export class ApproveComponent {
  public showMessage = false;
  public message: string;
  public body = 'Loading content for approval...';
  public loading = true;
  public permissions: NgxPermissionsObject;
  private id: string;
  private type: string;
  private approvalMessage = 'Are you sure the information is correct and you want to approve?';
  private resetMessage = 'Are you sure you want to reset this approval back to the start?';
  private rejectMessage = 'Are you sure you want to reject this approval? ' +
    'Rejecting an approval is permanent and will close this process and prevent it progressing further.';

  constructor(
    private router: Router,
    private route: ActivatedRoute,
    private service: ApprovalsService,
    private ngxPermissionsService: NgxPermissionsService,
    private messageService: MessageService,
    public confirmationDialog: ConfirmationDialogService) {
    this.route.params.subscribe(params => {
      this.id = params['id'];
      this.type = params['type'];
      this.loading = true;
      this.service.get(this.type, this.id).then(x => {
        if (!x) { return; }
        this.loading = false;
        this.body = x.body;
      });
    });
    this.permissions = this.ngxPermissionsService.getPermissions();
  }




  public confirmation = (type: 'Reset' | 'Reject' | 'Approve') => {
    if (!this.showMessage
      && ((type === 'Approve' && this.permissions.ViewNotes)
        || (type !== 'Approve'))) {
      this.showMessage = true;
      return;
    }

    if (!this.message
      && ((type === 'Approve' && this.permissions.ViewNotes)
        || (type !== 'Approve'))) {
      this.messageService.add('Message is required.', 'warning');
      return;
    }

    if (type === 'Approve') {
      this.confirmationDialog.show(this.approvalMessage, type, () => this.confirm(type));
    } else if (type === 'Reset') {
      this.confirmationDialog.show(this.resetMessage, type, () => this.confirm(type));
    } else if (type === 'Reject') {
      this.confirmationDialog.show(this.rejectMessage, type, () => this.confirm(type));
    }

  }

  public confirm = (type: 'Reset' | 'Reject' | 'Approve') => {
    let promise;

    if (type === 'Reset') {
      promise = this.service.reset(this.id, this.type, this.message);
    } else if (type === 'Reject') {
      promise = this.service.reject(this.id, this.type, this.message);
    } else if (type === 'Approve') {
      promise = this.service.approve(this.id, this.type, this.message);
    }


    promise.then(() => {
      this.messageService.add(`Successfully ${type}.`, 'info');
      this.navigateToApprovalList();
    });
  }


  private navigateToApprovalList = () => this.router.navigate(['/approvals']);
}

Тестовый компонент

describe('ApproveComponent', () => {
  let component: ApproveComponent;
  let injector: TestBed;
  let fixture: ComponentFixture<ApproveComponent>;
  const mockService: ApprovalsService = <ApprovalsService>{
    approve: (id: string, type: string, message: string) => <Promise<any>>{},
    reset: (id: string, type: string, message: string) => <Promise<any>>{},
    reject: (id: string, type: string, message: string) => <Promise<any>>{},
    get: (type: string, id: string) => <Promise<any>>{},
  };
  const mockRoute = { params: of({ id: '123', type: 'test' }), snapshot: {} };

  function setupComponent(getResult: any = {}) {
    spyOn(mockService, nameof<ApprovalsService>('approve')).and.returnValue(Promise.resolve({}));
    spyOn(mockService, nameof<ApprovalsService>('reset')).and.returnValue(Promise.resolve({}));
    spyOn(mockService, nameof<ApprovalsService>('reject')).and.returnValue(Promise.resolve({}));
    spyOn(mockService, nameof<ApprovalsService>('get')).and.returnValue(Promise.resolve(getResult));

    TestBed.configureTestingModule({
      imports: [
        DxTextAreaModule,
        DxButtonModule,
        SharedModule,
        RouterTestingModule.withRoutes([{ path: 'approvals', component: ApproveComponent }])
      ],
      declarations: [ApproveComponent],
      providers: [
        { provide: ApprovalsService, useValue: mockService },
        { provide: ActivatedRoute, useValue: mockRoute },
        { provide: MessageService, useClass: MockMessageService },
        { provide: ConfirmationDialogService, useValue: ConfirmationDialogServiceMock },
        { provide: NgxPermissionsService, useClass: MockNgxPermissionsService }
      ]
    })
      .compileComponents();

    fixture = TestBed.createComponent(ApproveComponent);
    injector = getTestBed();
    component = fixture.componentInstance;
    spyOn((<any>component).router, 'navigate').and.returnValue(true);

    fixture.detectChanges();
  }

  it('should create and call get', () => {
    setupComponent();

    expect(component).toBeTruthy();
    expect(mockService.get).toHaveBeenCalled();
  });

  it('should call get and do not set body on empty result', () => {
    setupComponent(null);

    expect(component).toBeTruthy();
    expect(component.body).toBe('Loading content for approval...');
  });

  it('should call confirmation dialog when accept confirmation is called', () => {
    setupComponent();
    const dialogService = injector.get(ConfirmationDialogService);
    const dialogServiceSpy = spyOn(dialogService, 'show').and.callThrough();
    component.showMessage = true;
    component.message = 'Approved because potato';
    fixture.ngZone.run(() => component.confirmation('Approve'));
    expect(dialogServiceSpy).toHaveBeenCalled();
    expect(dialogServiceSpy).toHaveBeenCalled();
  });



   it('should call reject confirmation dialog', () => {
    setupComponent();
    const dialogService = injector.get(ConfirmationDialogService);
    const dialogServiceSpy = spyOn(dialogService, 'show').and.callThrough();

    component.showMessage = true;
    component.message = 'rejected because potato';
    fixture.ngZone.run(() => component.confirmation('Reject'));
    expect(dialogServiceSpy).toHaveBeenCalled();
    expect(mockService.reject).toHaveBeenCalled();
  });

  it('should call reset confirmation dialog', () => {
    setupComponent();
    const dialogService = injector.get(ConfirmationDialogService);
    const dialogServiceSpy = spyOn(dialogService, 'show').and.callThrough();

    component.showMessage = true;
    component.message = 'rejected because potato';
    fixture.ngZone.run(() => component.confirmation('Reset'));
    expect(dialogServiceSpy).toHaveBeenCalled();
    expect(mockService.reset).toHaveBeenCalled();
  });

  it('should set showMessage when reject is called', () => {
    setupComponent();

    component.showMessage = false;
    fixture.ngZone.run(() => component.confirmation('Reject'));
    expect(component.showMessage).toBe(true);
    expect(mockService.reject).not.toHaveBeenCalled();
  });

  it('should not call service when reject is called and message is empty', () => {
    setupComponent();

    component.showMessage = true;
    component.message = '';
    fixture.ngZone.run(() => component.confirmation('Reject'));
    expect(mockService.reject).not.toHaveBeenCalled();
  });
});

1 Ответ

0 голосов
/ 20 января 2020

Это потому, что у каждого оператора if есть обязательный другой случай. Это если программа выходит из условия if true. Покрытие кода говорит вам, что окончательный случай "еще" не проверен. Вам необходимо добавить тест, который проверяет, что диалоговое окно не открывается, если указан неверный тип.

it('should call reset confirmation dialog', () => {
  setupComponent();
  const dialogService = injector.get(ConfirmationDialogService);
  const dialogServiceSpy = spyOn(dialogService, 'show').and.callThrough();

  component.showMessage = true;
  component.message = 'rejected because potato';
  fixture.ngZone.run(() => component.confirmation('bad-type' as any));
  expect(dialogServiceSpy).not.toHaveBeenCalled();
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...