1

I have written the following code with async unit testing but these are failing randomly not consistently. Can anyone help me what here wrong?

The test case is: When the user pressed keyboard keys W (go to the previous doc) and S(go to next doc) then on UI selected document(row) should be changed in table.

    it('When user press key W and S then should be able navigate to previous and next document', async () => {
                createTestBed();
                fixture.detectChanges();
                const searchResultStub = MockNgRedux.getSelectorStub(['documentSearch', 'results']);
                searchResultStub.next(getSearchResult());
                searchResultStub.complete();
                fixture.detectChanges();
    
                const spyPrevElement = spyOn(comp.documentSearchResult._tableService, 'selectPrevElement').and.callThrough();
                const spysNextElement = spyOn(comp.documentSearchResult._tableService, 'selectNextElement').and.callThrough();
    
                await TestUtil.SleepForASecond(0);
                document.dispatchEvent(TestUtil.createKeyUpEvent("S"));
                fixture.detectChanges();
                expect(spysNextElement).toHaveBeenCalled();
                expect(spysNextElement).toHaveBeenCalledTimes(1);
    
                document.dispatchEvent(TestUtil.createKeyUpEvent("W"));
                fixture.detectChanges();
                expect(spyPrevElement).toHaveBeenCalled();
                expect(spyPrevElement).toHaveBeenCalledTimes(1);
            });

TestUtil.ts file:

static async SleepForASecond(ms) {
    await new Promise(resolve => setTimeout(resolve, ms);
  }

 static createKeyUpEvent(key: string, isCapsOn: boolean = false) {
    const keyUpEvent: Event = new KeyboardEvent('keyup', {
      'key': key,
      'modifierCapsLock': isCapsOn
    });
    return keyUpEvent;
  }

Similar for this other tests are failing due to async and await with the following error. Can anyone have an idea?

Error: Timeout - Async callback was not invoked with 5000ms(set by jasmine.DEFAULT_TIMEOUT_INTERVAL) at <Jasmine>

OBSERVATION: TEST CASES ARE MORE FAILING INSIDE DOCKER CONTAINER. TESTS WOULD SOMETIMES PASS WITHOUT ANY ISSUES BUT SOMETIMES FAIL.

Anshita Singh
  • 1,583
  • 1
  • 17
  • 40

1 Answers1

0

By default Jasmine (your testing framework) will wait 5 seconds for an asynchronous method to callback. If it doesn't you get the error presented to you here. All it's really saying is the asynchronous method was called, five seconds passed, and it didn't return so throw an error.

The reason the tests are failing randomly is that sometimes your asynchronous function call is returning on time and sometimes it isn't.

As per the jasmine documentation you can change the default timeout globally with just the line:

jasmine.DEFAULT_TIMEOUT_INTERVAL = time;

Where time is the maximum timeout you want in milliseconds (10000 would be 10 seconds).

If you would prefer to set it for each specific instance, you can read the full syntax for this in the documentation here: https://jasmine.github.io/2.1/introduction.html#section-47.

TheWriter
  • 256
  • 1
  • 5
  • yes, I know by increasing DEFAULT_TIMEOUT_INTERVAL can help. But is there any other way. Is there any wrong with this test case? What causing to asynchronous function is not returning on time? – Anshita Singh Jul 23 '20 at 08:14
  • There isn't anything wrong with it necessarily, functions don't always take the same amount of time since there are multiple factors involved. You may want to try logging the amount of time each portion of your function takes, then you will know what is taking up what percent of the time. You can do this using "console.time", see (https://developer.mozilla.org/en-US/docs/Web/API/Console/time). This allows you to hook into a function call and output the actual time (in ms) taken by that function to the console. – TheWriter Jul 23 '20 at 08:53
  • But if I'll increase DEFAULT_TIMEOUT_INTERVAL as of now, so will it be a guarantee that in later I don't have to increase more? Maybe that's why I wanted to find another solution instead of increasing the time since It will not guarantee that later I don't have to change more. – Anshita Singh Jul 23 '20 at 09:13
  • If you wanted to make your asynchronous function quicker, you either have to optimize its functionality or remove some of its functionality. Without seeing the entirety of your code it's hard to say what can be optimized, but perhaps if your testing for both "W" and "S" in the same function, you could separate them out into two different tests. – TheWriter Jul 23 '20 at 09:30