单元测试Angular Observables

时间:2016-11-14 15:46:24

标签: angular jasmine primeng

我是测试世界的新手,我刚开始为现有的Angular 2代码编写单元测试。我有一个函数confirmDelete,它返回Obserable<boolean>并在内部使用PrimeNG的ConfirmationService来获取用户对弹出窗口的反馈。

该功能的定义如下:

confirmDelete(): Observable<boolean> {
    let confirmObservable = Observable.create((observer: Observer<boolean>) => {            
        this.confirmationService.confirm({
            header: 'Delete Confirmation',
            message: 'Do you really want to delete this record?',
            accept: () => {
                observer.next(true);
                observer.complete();            
            },
            reject: () => {
                observer.next(false);
                observer.complete();
            }
        });

    });

    return confirmObservable;

}

我想为这段代码编写单元测试。我计划为ConfirmationService写一个Stub,但由于我是单元测试世界的新手,我发现很难设置这些东西。

我的问题是在这种特定情况下编写单元测试的正确方法是什么。

编辑: -

我尝试了@peeskillet提出的解决方案,但后来我开始在ConfirmationServiceMockConfirmationService之间出现类型不匹配错误。

以下是在PrimeNG库中找到的ConfirmationServiceConfirmation类的声明。

export interface Confirmation {
    message: string;
    icon?: string;
    header?: string;
    accept?: Function;
    reject?: Function;
    acceptVisible?: boolean;
    rejectVisible?: boolean;
    acceptEvent?: EventEmitter<any>;
    rejectEvent?: EventEmitter<any>;
}
export declare class ConfirmationService {
    private requireConfirmationSource;
    private acceptConfirmationSource;
    requireConfirmation$: Observable<Confirmation>;
    accept: Observable<Confirmation>;
    confirm(confirmation: Confirmation): this;
    onAccept(): void;
}

2 个答案:

答案 0 :(得分:4)

我可能会模仿acceptreject函数的引用。然后在测试中,您可以调用它们来检查它们是否发出了正确的布尔值。像

这样的东西
class MockConfirmationService {
  accept: Function;
  reject: Function;

  confirm(config: any) {
    this.accept = config.accept;
    this.reject = config.reject;
  }
}

然后在测试中,只需调用accept来测试true是否已发出,并调用reject来测试false是否已发出。

describe('serivce: ModalService', () => {

  let modalService: ModalService;
  let confirmService: MockConfirmationService;

  beforeEach(() => {
    confirmService = new MockConfirmationService();
    TestBed.configureTestingModule({
      providers: [
        ModalService,
        { provide: ConfirmationService, useValue: confirmService }
      ]
    });

    modalService = TestBed.get(ModalService);
  });

  it('should return true when accepted', async(() => {
    modalService.confirmDelete().subscribe(result => {
      expect(result).toBe(true);
      console.log('accepted test complete');
    });
    confirmService.accept();
  }));

  it('should return false when rejected', async(() => {
    modalService.confirmDelete().subscribe(result => {
      expect(result).toBe(false);
      console.log('rejected test complete');
    });
    confirmService.reject();
  }));
});

答案 1 :(得分:0)

我已经建立了peeskillet的答案。 p-confirmDialog 组件调用该服务的订阅,因此我必须添加 requireConfirmationSource ,我找到了在PrimeNg源代码中。我的模拟如下:

//
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
//
export class ConfirmationServiceMock {
    public key: string = 'mock1';
    public header: string = 'Delete Confirmation';
    public icon: string = '';
    public message: string = '';
    //  Call Accept to emulate a user accepting
    public accept: Function;
    //  Call Reject to emulate a user rejecting
    public reject: Function;
    private requireConfirmationSource = new Subject<any>();
    requireConfirmation$ = this.requireConfirmationSource.asObservable();
    //
    public confirm(config: any) {
        console.log( 'In confirm service mock...' );
        this.message = config.message;
        this.accept = config.accept;
        this.reject = config.reject;
        console.log( this.message );
        return this;
    }
}
//