Question

Can you test whether a function is actually running Asynchronously?

I'm working on a ASP.NET Web Api project to learn the framework and the testing for it and I was wondering if you could test that Asynchronous methods are actually running Asynchronously (or are they running Synchronously due to any errors for example).

    public class RepositoryBase<Tentity, Tcontext> : IRepositoryBase<Tentity> where Tentity : class where Tcontext : DbContext
    {
        protected Tcontext _RepositoryContext;
        protected DbSet<Tentity> dbSet;
        public RepositoryBase(Tcontext context)
        {
            this._RepositoryContext = context;
            dbSet = _RepositoryContext.Set<Tentity>();
        }
        public async Task Create(Tentity entity)
        {
            await dbSet.AddAsync(entity);
        }
    }

Can you Test whether the Create method is actually running asynchronously? Is it logical to test whether a method is running asynchronously? Or is it a trivial concern because the fact that it's returning a Task is proof it is running asynchronously.

During unit testing, in my test function, I only tried await repository.Create(testUser); and then later Asserted that the user inside the database and the one I inputted are identical in all aspects. But that's just testing the end functionality of the Create function and not whether its successfully running asynchronously or not.

My aim is not to test or question this specific framework itself but to question if any generic async function could be tested for its asynchronous nature. The example code above is just the context under which this question appeared in my head.

 3  80  3
1 Jan 1970

Solution

 6

Can you test whether the Create method is actually running asynchronously?

Yes, but not with 100% confidence. You can test that the method returns a Task that has not completed yet. Instead of:

await repository.Create(testUser);

...do this:

Task task = repository.Create(testUser);
Debug.Assert(!task.IsCompleted);
await task;
  • If the task.IsCompleted is false, it means that the task will complete asynchronously in the future.
  • If the task.IsCompleted is true, it means that either completed synchronously, or that it completed asynchronously so fast that you didn't have the chance to observe it (extremely unlikely scenario).
2024-07-03
Theodor Zoulias

Solution

 2

That question makes not much sense IMHO. Imagine a sync function like this one:

int DoSomething(int i) { ... }

From a consumer-perspective all you know - and all you should test for - is what the function expects and what it returns in that case. You would never come to the assumption to check if the function really does anything with the parameter. Instead you just check its return-value.

Your async code is in no way different: it returns a Task, which pretends there's some async code running inside of it.

Task DoSomething() { ... }

When calling this function we just care for its externals, not its actual implementation. We have no way to check what it does internally. We can just assume that something async code is there. Even the async keyword tells us nothing. If the function was defined on an interface, async wouldn't even exist, so we couldn't rely on that either.

So afterall there's no point on testing if the function really calls into any async code, or if it just pretends to do; the same as in the first example if it really uses the parameter.

2024-07-03
MakePeaceGreatAgain