1

I am using Angular 7+.

Summary of the problem :

I have a code inside which there is a setInterval method which calls a url method of a service to retrieve data every 1000 milliseconds. Also note that i do not want my program to first wait for 1000 ms and then call the url method, i.e why i have pre called the method only once before setInterval. Do let me know how to test this exact same behaviour. Also please do not bother much about the implementation as it is done according to business requirement which i cannot disclose.

Problem Statement:

Suppose i have a url to which i check every 1 second whether i am getting data or not. The call to this url is made inside a function getDataFromUrl , inside a service injected into the component.

Please refer the code below.

someStorage = {};

constructor(private service: someService){}
ngOnDestroy(){
   clearInterval(this.clearPeriodicRefresh);
}

ngOnChanges(){
    let context = this;
    this.periodicRefresh(context);
    this.clearPeriodicRefresh = setInterval(function(){
        this.periodicRefresh(context);
    },1000);
}

periodicRefresh(self){
    self.service.getDataFromUrl(url).subscribe(res => {
        someStorage[res] = true;
    },
    err =>{
       console.log(" Error Occured "); 
    });
}

Now i am unit testing the code like this:

it('should check for async data from url', fakeAsync()=>{
    someServiceStub.getDataFromUrl.and.returnValue(of("chandni chowk"));
    fixture.detectChanges();
    expect(component.someStorage["chandni chowk"]).toBe(true); // executes successfully
    
    setInterval(()=>{
        someServiceStub.getDataFromUrl.and.returnValue(of("delhi"));    
    },1000);
    
    tick(1000); // in milliseconds
    discardPeriodicTasks();
    
    expect(component.someStorage["delhi"]).toBe(true);          // throws error
    
}));

The second expect statement shows :

ERROR : expected undefined to be true

I do not know the reason why . However, if i do a tick(2000) instead of tick(1000), then it works. Again i am not sure why it gets skipped earlier.

NOTE : Any timer between 1000 and 2000 i.e for example till tick(1900) throws the same error, and anytime after 2000 milliseconds works fine.

Also please tell me how to write better tests if there is any other way for this.

11
  • 1
    Hi mate, setInterval on ngOnChanges is a bad idea with not clearing the interval, as it is always adding a new interval function. Also you could just use an arrow function on setInterval like this setInterval(() => { ... } and there shouldnt be any need for passing any context around, as "this" is component wide context in angular. BTW what are u trying to test here? Your storage? Your service? Your component? regards Commented Jun 15, 2020 at 20:20
  • 1
    Please provide a stackblitz with your setup. Commented Jun 15, 2020 at 20:23
  • Hello @sagat, please see the edited code. Commented Jun 15, 2020 at 20:25
  • clearInterval(this.clearPeriodicRefresh); this wont help on ngOndestroy, as ngOnChanges is called way more often during component lifetime, while onDestroy is only called when the component disappears. Commented Jun 15, 2020 at 20:29
  • 1
    @KL_KISNE_DEKHA_HAI You cannot ignore Sagat's comments relating to ngOnChanges as this may be the root of your problem. Commented Jun 21, 2020 at 14:56

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.