Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 7 Testing - Async function call + async..await

In an Angular 7 unit test, is there a way to avoid the double async( async(){} ) syntax when combining async support along with the async..await keywords?

I'm new to angular but am an experienced programmer, and I'm having trouble landing on my preferred test style.

I would like to safely use async..await in tests, and I understand the below syntax. However, when instructing devs new to modern javascript and/or the concept of async..await the double async(async()) syntax is redundant and confusing to them. They are leaving out the outer async. Exceptions thrown in the service are causing failures to be reported outside of the actual test which is difficult to track down.

It seems like one of the following would be better:

  1. it() should magically support async..await and wrap my callback in async() so that I don't have to think about it.
  2. it() should take an optional function parameter (i.e., async or fakeAsync) that will wrap my callback.
  3. it() variations ita() and itfa() should exist that will wrap my callback with the appropriate async helper.
  4. it() wraps my callback with async, and an additional itf() will wrap my callback in fakeAsync.

Am I missing an existing concept or syntax? Is there a better alternative?

    import { async } from '@angular/core/testing';

    describe('MyService', () => {
        let service: MyService;

        ...

        it('should get data', async( async() => {
            // arrange
            let expectedData = { answer: 42 };

            // act
            let data = await service.getDataAsync();

            // assert
            expect(data).toEqual(expectedData);
        } ));
    })
like image 975
Jason Avatar asked Mar 02 '19 22:03

Jason


People also ask

How can you wrap a function in async testing?

fakeAsync and tick Like async we wrap the test spec function in a function called fakeAsync . We call tick() when there are pending asynchronous activities we want to complete. Like the async function the fakeAsync function executes the code inside its body in a special fake async test zone.

Do you need await to call async function?

async and await Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

Can you call an async function?

Handling errors in async functions is very easy. Promises have the . catch() method for handling rejected promises, and since async functions just return a promise, you can simply call the function, and append a . catch() method to the end.


1 Answers

there are a couple different ways to handle async testing:

  1. Use the built-in karma doneFunction: (doneFunction) => {async test here... then eventually call done();}. It gives you fine-grain control over where your test ends, but makes you kinda handle errors on your own with done.fail(error).
  2. Wrap in the angular async() function. This is part of your example above, but as you noted, it seems that the Angular async function doesn't automatically support await syntax inside, thus necessitating the use of the inner async to get support for await.
  3. Use the Angular fakeAsync() wrapper function, which allows you to call tick() wherever in your code to simulate the passage of time and resolution of observables, promises, and other async functions. One downside: you can't do HTTP calls in this, since they would happen real-time.

Although I've found each of the 3 methods has pros & cons, I have found #2 to be the most useful for creating a smooth flowing test that is easily readable. So although you could avoid the nested async code with using #1 or #3, I'm not sure the benefit would outweigh the costs. As far as your suggestions, you may want to consider submitting a feature request to the angular repo if its important to you.

For more info, I found this source to be quite helpful: https://medium.com/@michaelericksen_12434/angular-asynchronous-test-patterns-and-recipes-202cf7d47ec7. Hope that helps!

like image 108
RocketMan Avatar answered Oct 20 '22 12:10

RocketMan