Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit tests and multiple async tasks

I'm creating unit tests to assist with building some code which will accept and queue (if needed) inbound requests from my controller.

In my unit test I want two lines of code to fire off pretty much at the same time, albeit with a 2 second delay between the calls. This allows the first branch of my logic to be triggered, then on the second call because the passed data is already seen the alternate branch of logic is used.

I've come close but it feels messy. I'm using the following which immediately passes off my first call and moves on to the subsequent lines of code.

Task.Factory.StartNew(() => stubbedQueueHandler.QueueProcessor(setupModel));

Thread.Sleep(2000);
//second call
stubbedQueueHandler.QueueProcessor(setupModel);

await Task.Delay(10000);

However the unit test concludes ahead of the first call finishing, which in turn kills the process. The only way to allow the first call to complete is to put an await Task.Delay() line which does the trick.

I can see why it's doing it, because I've effectively handed off the call with no expectation of a response coming back. I don't want to start using task delays and I'm sure it's just my lack of understanding that's the problem when it comes to async programming :o).

like image 895
Sulphy Avatar asked Mar 15 '23 05:03

Sulphy


1 Answers

What you need is to capture the Task which kicks off QueueProcessor and await it after calling the stub for the second time:

public async Task FooTestAsync()
{
    var task = Task.Run(() => stubbedQueueHandler.QueueProcessor(setupModel));
    await Task.Delay(2000);

    stubbedQueueHandler.QueueProcessor(setupModel);
    await task;
}

This way, you ensure the completion of the operation before the operation completes, given that the QueueProcessor will synchronously block until its operation is complete.

like image 138
Yuval Itzchakov Avatar answered Mar 23 '23 03:03

Yuval Itzchakov