Angular 9 Модульное тестирование ngOnInit с внутренним сервисом setTimeOut - PullRequest
0 голосов
/ 04 мая 2020

У меня есть компонент с функцией setTimeOut внутри службы. Для написания модульных тестов для этого я использую tick и fakeAsyn c для setTimeOut. Но это не выполняется. даже меня интересует, как мне написать тестовый пример для окна ['MyAirtelAppReact'] внутри условия if.

И я попытался с помощью flushMicrotasks очистит все из микрозадач, которые в данный момент находятся в очереди, но не уверены, так ли это? Как бы я написал модульный тест, чтобы проверить это?

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


constructor(
    private dataService: DataService,
    private loadinSrvc: LoadingService,
    private router: Router,
    private toastr: ToastrService,
    public dialog: MatDialog
  ){
  if (window['MyAirtelAppReact'] !== undefined) {
    if (
      window['MyAirtelAppReact'] &&
      window['MyAirtelAppReact'].getParameters
    ) {
      const deviceInfoString = window['MyAirtelAppReact'].getParameters();
      const deviceInfo = JSON.parse(deviceInfoString);
      this.dataService.setAppDetails(deviceInfo);
    }
  } else if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
    window['webkit'].messageHandlers.getParameters.postMessage('');
  } else {
    const deviceInfo = {
      channel: 'web',
      deviceId: GLOBAL_PROPERTIES.DEVICE_ID,
    };
    this.dataService.setAppDetails(deviceInfo);
  }

  this.loadinSrvc.userChangeEvent.subscribe((user) =>
    setTimeout(() => {
      this.showLoader = {
        text: this.loadinSrvc.getLoaderText() || 'Please wait...',
        isLoader: user,
      };
    })
  );

  this.router.events.subscribe((event: Event) => {
    if (event instanceof NavigationEnd) {
      this.loadinSrvc.setLoader(false);
    }
    if (event instanceof NavigationStart) {
      this.loadinSrvc.setLoader(true);
    }
    if (event instanceof NavigationError) {
      this.toastr.error('Something went wrong, please retry.');
      this.loadinSrvc.setLoader(false);
    }
  });
}

Spe c Файл:

describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        ReactiveFormsModule,
        RouterTestingModule,
        CommonModule,
        HttpClientModule,
        ToastrModule.forRoot({
          timeOut: 3000,
          positionClass: 'toast-bottom-right',
          maxOpened: 1,
          preventDuplicates: true,
        }),
        MatDialogModule,
      ],
      declarations: [AppComponent],
      providers: [
        CommonService,
        { provide: DataService, useClass: MockDataService },
      ],
    }).compileComponents();
  }));

  // try2
  it('should test some asynchronous code', fakeAsync(() => {
    const fixture = TestBed.createComponent(AppComponent);
    const component = fixture.componentInstance;
    fixture.detectChanges();
    component.showLoader = { isLoader: false, text: 'Please wait...' };

    const testObservable = from(Promise.resolve(true));
    let flag = false;

    testObservable.subscribe((result) => {
      flag = true;
    });

    flushMicrotasks();
    expect(flag).toBe(true); // PASSES
  }));
});

1 Ответ

0 голосов
/ 04 мая 2020

Ниже приведен простой тест, который оценивает как MyAirtelAppReact case, так и showLoader внутри setTimeout функции (я добавил несколько комментариев, но не стесняюсь спрашивать):

import SpyObj = jasmine.SpyObj;
import createSpy = jasmine.createSpy;
import spyOn = jasmine.spyOn;
import createSpyObj = jasmine.createSpyObj; 
describe('test set', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;
  let dataServiceSpy: SpyObj<DataService>;
  let toastrServiceSpy: SpyObj<ToastrService>;
  let matDialogSpy: SpyObj<MatDialog>;
  const loadingServiceMock = {userChangeEvent: {subscribe: createSpy()}, getLoaderText: createSpy()};
  const routerMock = {events: {subscribe: () => null}};

  beforeEach(async(() => {
    dataServiceSpy = createSpyObj('DataService', ['setAppDetails']);
    toastrServiceSpy = createSpyObj('ToastrService', ['error']);
    matDialogSpy = createSpyObj('MatDialog', ['']);

    TestBed.configureTestingModule({
      declarations: [AppComponent],
      providers: [
        {provide: DataService, useValue: dataServiceSpy},
        {provide: LoadingService, useValue: loadingServiceMock},
        {provide: Router, useValue: routerMock},
        {provide: ToastrService, useValue: toastrServiceSpy},
        {provide: MatDialog, useValue: matDialogSpy},
      ]
    }).compileComponents();
  }));

  // Had to move "beforeEach" function body here as your code execute in component class constructor
  function setUp() {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }

  it('test 1', fakeAsync(() => {
    // Won't create Observable and only spy upon "Observable" methods that are being used
    loadingServiceMock.userChangeEvent.subscribe.and.callFake(cb => cb({name: 'Some Fake User Data'}));
    // Here is null but can be anything else - eg. in other tests
    loadingServiceMock.getLoaderText.and.returnValue(null);
    // Won't run built in method but can be worth to check what was passed in and out
    spyOn(JSON, 'parse');
    // Create spy for further checks and it results to evaluate true in "if" check
    window['MyAirtelAppReact'] = {getParameters: createSpy()};

    setUp();

    expect(JSON.parse).toHaveBeenCalled(); // check for MyAirtelAppReact
    expect(dataServiceSpy.setAppDetails).toHaveBeenCalled(); // check for MyAirtelAppReact

    tick(); // For setTimeout

    expect(component.showLoader).toEqual({
      text: 'Please wait...',
      isLoader: {name: 'Some Fake User Data'}
    });
  }));
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...