Mock Idle in Angular 4 Unit tests

二次信任 提交于 2020-08-26 02:51:09

问题


I am trying to write unit tests for Angular4 app using karma after this I am getting error at TestBed.createComponent(ServicesComponent) so none of the test cases are being executed, and

TypeError: this.expiry.last is not a function at Idle.Array.concat.Idle.watch...

There is a lot of stuff written in the constructor(in which there are service calls being made and also Idle functionality was written), How would the test cases should be written for that?

This is my spec file, Idle functions are used in Component's Constructor, and I had to add IdleExpiry, Keepalive providers to not get exceptions like Error: No provider for IdleExpiry

beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [                    
                ServicesComponent
            ],
            providers: [
                { provide: ServicesService, useClass: ServicesService },
                { provide: LocalStorageService, useClass: MockLocalStorageService },
                { provide: ServiceUtilities, useClass: ServiceUtilities },
                { provide: Idle, useClass: Idle },
                { provide: IdleExpiry, useClass: IdleExpiry },
                { provide: Keepalive, useClass: Keepalive },
                { provide: Router, useValue: routerStub },
                { provide: ActivatedRoute, useValue: activatedrouteStub },
                MockBackend,
                BaseRequestOptions,
                {
                    provide: Http,
                    useFactory: (backend, options) => new Http(backend, options),
                    deps: [MockBackend, BaseRequestOptions]
                }
            ],
            imports: [
                ModalModule.forRoot()
            ]
        }).compileComponents();
    }));
beforeEach(() => {            
        fixture = TestBed.createComponent(ServicesComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
    });

Component (excluding unneccessary details (replaced by ...))

export class ServicesComponent {
    ...
    approxWaitingTime: string;
    idleState = 'Not started.';
  timedOut = false;
  lastPing?: Date = null;
@ViewChild('autoShownModal') public autoShownModal: ModalDirective;
public isModalShown:boolean = false;
timer: any;
constructor(private servicesService: ServicesService, private route: ActivatedRoute, private router: Router, private idle: Idle, private keepalive: Keepalive) {

    this.servicesService.getServices(this.centerId).subscribe(data => { ... });
    this.servicesService.getCategories(this.centerId).subscribe(data => {  ... });
    this.servicesService.getStylists(this.centerId).subscribe(data => { ... });
    this.servicesService.getApproxWaitingTime(this.centerId).subscribe(data => { ... });

    this.route.queryParams.subscribe(params => { ... });

    // sets an idle timeout of 120 seconds, for testing purposes.
    idle.setIdle(10);
    // sets a timeout period of 30 seconds. after 30 seconds of inactivity, the user will be considered timed out.
    idle.setTimeout(5);
    // sets the default interrupts, in this case, things like clicks, scrolls, touches to the document
    idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);

    idle.onIdleEnd.subscribe(() => this.idleState = 'No longer idle.');
    idle.onTimeout.subscribe(() => {
        console.log("ontimeout");
        this.idleState = 'Timed out!';
        this.timedOut = true;
    });
    idle.onIdleStart.subscribe(() => this.idleState = 'You\'ve gone idle!');
    idle.onTimeoutWarning.subscribe((countdown, router, autoShownModal) => {
        console.log("time out" + countdown);
        this.isModalShown = true;
        this.timer = setTimeout(function () { if (this.isModalShown) { this.hideModal(); } this.reset(); this.router.navigate(['']); }.bind(this), 3000);
        this.reset();
    });

    // sets the ping interval to 15 seconds
    keepalive.interval(10);

    keepalive.onPing.subscribe(() => { this.lastPing = new Date(); console.log('Keepalive.ping() called!'); });

    this.reset();
}
...

Am I missing any?


回答1:


Here's what I did to make the component load, Mocked IdleExpiry

export class MockExpiry extends IdleExpiry {
  public lastDate: Date;
  public mockNow: Date;

  last(value?: Date): Date {
    if (value !== void 0) {
      this.lastDate = value;
    }

    return this.lastDate;
  }

  now(): Date {
    return this.mockNow || new Date();
  }
}

updated the spec

providers: [
...
    { provide: IdleExpiry, useClass: MockExpiry },
...
],



回答2:


The proper solution would have been to add the NgIdleKeepaliveModule to the imports of the testingModule.

I also would suggest against extending the class that you are mocking in a mock (implementing wouldn't be a bad idea however).



来源:https://stackoverflow.com/questions/43919222/mock-idle-in-angular-4-unit-tests

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