Search code examples
c#.netunit-testingparallel-processing

How to simulate long running process in .NET API Controller Correctly


I am trying to create a unit test to simulate my API being called by many people at the same time.

I've got this code in my unit test:

var tasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
    var id = i; // must assign to new variable inside for loop
    var t = Task.Run(async () =>
    {
        response = await Client.GetAsync("/api/test2?id=" + id);
        Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
    });
    tasks.Add(t);
}

await Task.WhenAll(tasks);

Then in my controller I am putting in a Thread.Sleep.
But when I do this, the total time for all tests to complete is 10 x the sleep time.

I expected all the calls to be made and to have ended up at the Thread.Sleep call at more or less the same time.

But it seems the API calls are actually made one after the other.

The reason I am testing the parallel API call is because I want to test a deadlock issue with my data repository when using SQLite which has only happened when more than 1 user uses my web site at the same time.

And I have never been able to simulate this and I thought I'd create a unit test, but the code I have now seems to not be executing the calls in parallel.

My plan with the Thread.Sleep calls was to put a couple in the Controller method to make sure all requests end up between certain code blocks at the same time.

Do I need to set a a max number of parallel requests on the Web Server or something or am I doing something obviously wrong?

Update 1: I forgot to mention I get the same results with await Task.Delay(1000); and many similar alternatives.

Not sure if it's clear but this is all running within a unit test using NUnit.
And the "Web Server" and Client is created like this:

var builder = new WebHostBuilder().UseStartup<TStartup>();           
Server = new TestServer(builder);
Client = Server.CreateClient();

Solution

  • I found the problem with my test.
    It was not the TestServer or the client code, it was the Database code.

    In my controller I was starting an NHibernate Transaction, and that was blocking the requests because it would put a lock on the table being updated.

    This is correct, so I had to change my code a bit to not automatically start a transaction. But rather leave that up to the calling code to manage.