web-dev-qa-db-ja.com

ng-bootstrap modal(NgbModal)の単体テストを書く[Angular 6]

アプリにある確認モーダルの単体テストの記述に問題があります。これが私がテストしたいコードの一部です:

  confirmModal(Prompt = 'Are you sure?', title = 'Confirm'): Observable<boolean> {
    const modal = this.ngbModal.open(
      ConfirmModalComponent, { backdrop: 'static' });

    modal.componentInstance.Prompt = Prompt;
    modal.componentInstance.title = title;

    return from(modal.result).pipe(
      catchError(error => {
        console.warn(error);
        return of(undefined);
      })
    );
  }

提案や例はありますか?

3
Amir

コードスニペットに基づいて、次のテストクラスを作成しました。

_import { TestBed, ComponentFixture } from '@angular/core/testing';
import { NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { ConfirmModalComponent } from './confirm-modal.component';
import { MyComponent } from './test';

// Mock class for NgbModalRef
export class MockNgbModalRef {
    componentInstance = {
        Prompt: undefined,
        title: undefined
    };
    result: Promise<any> = new Promise((resolve, reject) => resolve(true));
}

describe('MyComponent tests', () => {

    let fixtureUnderTest: ComponentFixture<MyComponent>;
    let componentUnderTest: MyComponent;
    let ngbModal: NgbModal;
    let mockModalRef: MockNgbModalRef = new MockNgbModalRef();

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [
                MyComponent
            ],
            imports: [
                NgbModule.forRoot()
            ]
        }).compileComponents();

        fixtureUnderTest = TestBed.createComponent(MyComponent);
        componentUnderTest = fixtureUnderTest.componentInstance;
        ngbModal = TestBed.get(NgbModal);
    });

    it('should open modal', () => {
        spyOn(ngbModal, 'open').and.returnValue(mockModalRef);
        componentUnderTest.confirmModal();
        expect(ngbModal.open).toHaveBeenCalledWith(ConfirmModalComponent, { backdrop: 'static' });
    });

    it('should set Prompt and title to defaults', () => {
        spyOn(ngbModal, 'open').and.returnValue(mockModalRef);
        componentUnderTest.confirmModal();
        expect(mockModalRef.componentInstance.Prompt).toBe('Are you sure?');
        expect(mockModalRef.componentInstance.title).toBe('Confirm');
    });

    it('should return the result of the modal', (done: DoneFn) => {
        spyOn(ngbModal, 'open').and.returnValue(mockModalRef);
        componentUnderTest.confirmModal().subscribe((result: boolean) => {
            expect(result).toBe(true);
            done();
        });
    });

    it('should return undefined if there is an error', (done: DoneFn) => {
        spyOn(ngbModal, 'open').and.returnValue(mockModalRef);
        // Override the result returned from the modal so we can test what happens when the modal is dismissed
        mockModalRef.result = new Promise((resolve, reject) => reject(false));
        componentUnderTest.confirmModal().subscribe((result: boolean) => {
            expect(result).toBeUndefined();
            done();
        });
    });

});

_

テストは次のとおりです。

  1. モーダルを開く必要があります: _ngbModal.open_メソッドが正しいパラメーターで呼び出されたことをテストします.

  2. Promptおよびtitleをデフォルトに設定する必要があります:Promptおよびtitle属性がデフォルト値に正しく設定されていることをテストしますモーダルが開きました。このために、次のオブジェクトをMockNgbModalRefに追加して、プロンプトとタイトルの値をコンポーネント自体が更新できるようにする必要がありました。

_componentInstance = {
    Prompt: undefined,
    title: undefined
};
_
  1. モーダルの結果を返す必要があります: _modal.result_の値がこのメソッドから返されることをテストします。メソッドがObservableを返すので、それをサブスクライブし、サブスクライブ内でアサートを実行する必要がありました。アサーション後にdone()が呼び出されるようにDoneFnを注入しました。つまり、アサーションが発生しない場合(たとえば、コンポーネントにエラーがある場合)、done()が呼び出されることはなく、テストは失敗します。

  2. エラーがある場合はundefinedを返す必要があります:#3と同様ですが、モーダルの結果が拒否された(つまり、エラーがあった)場合にundefinedが返されることを確認します。

1
Ian A