Unit Testing Angular Observables

自作多情 提交于 2019-12-20 03:15:14

问题


I am new to testing world and I have just started writing unit tests for an existing Angular 2 code. I have a function confirmDelete which returns Obserable<boolean> and internally uses ConfirmationService of PrimeNG to get user's feedback on a popup.

Definition of the function is given below:

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;

}

I want to write a unit test for this piece of code. I planned to write a Stub for the ConfirmationService but because I am new to unit testing world, I am finding it difficult to set up the things.

My question is what is the correct approach to write a unit test in this particular scenario.

EDIT:-

I tried solution proposed by @peeskillet but then I started getting type mismatch error between ConfirmationService and MockConfirmationService.

Below are the declarations of ConfirmationService and Confirmation classes found in the PrimeNG library.

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;
}

回答1:


I would probably make the mock hold on to the references of the accept and reject functions. Then in the test you can call them to check that they emit the correct boolean value. Something like

class MockConfirmationService {
  accept: Function;
  reject: Function;

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

Then in your test just call the accept to test that true is emitted, and call reject to test that false is emitted.

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();
  }));
});



回答2:


I've built off of peeskillet's answer. The p-confirmDialog component calls the subscribe of the service, so I had to added requireConfirmationSource, which I found in the PrimeNg source. My mock is as follows:

//
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;
    }
}
//


来源:https://stackoverflow.com/questions/40592637/unit-testing-angular-observables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!