如何在.NET API控制器中正确模拟长时间运行的进程

问题描述 投票:0回答:3

我正在尝试创建一个单元测试来模拟我的 API 被很多人同时调用。

我的单元测试中有这段代码:

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);

然后在我的控制器中我放入一个

Thread.Sleep

但是当我这样做时,完成所有测试的总时间是睡眠时间的 10 倍。

我预计所有电话都会或多或少同时拨打并结束于

Thread.Sleep
电话。

但是 API 调用似乎是一个接一个地进行的。

我测试并行 API 调用的原因是因为我想测试使用 SQLite 时数据存储库的死锁问题,这种情况仅在超过 1 个用户同时使用我的网站时才会发生。

我从来没有能够模拟这个,我想我应该创建一个单元测试,但我现在拥有的代码似乎没有并行执行调用。

我对 Thread.Sleep 调用的计划是在 Controller 方法中放置几个调用,以确保所有请求同时在某些代码块之间结束。

我是否需要在 Web 服务器上设置最大并行请求数或其他什么,或者我是否做了一些明显错误的事情?

更新1: 我忘了提及我使用

await Task.Delay(1000);
和许多类似的替代方案得到了相同的结果。

不确定是否清楚,但这都是在使用 NUnit 的单元测试中运行的。
“Web 服务器”和客户端是这样创建的:

var builder = new WebHostBuilder().UseStartup<TStartup>();           
Server = new TestServer(builder);
Client = Server.CreateClient();
c# .net unit-testing parallel-processing
3个回答
0
投票

您可以使用

Task.Delay(time in milliseconds)
Thread.Sleep
不会释放线程,并且在等待结果时无法处理其他任务。


0
投票

.NET 中的

HttpClient
类默认限制对同一服务器的两个并发请求,我认为这可能会导致本例中的问题。通常,可以通过创建新的
HttpClientHandler
并将其用作构造函数中的参数来覆盖此限制:

new HttpClient(new HttpClientHandler
            {
                MaxConnectionsPerServer = 100
            })

但是因为客户端是使用

TestServer
方法创建的,所以事情变得有点复杂。您可以尝试更改
ServicePointManager.DefaultConnectionLimit
属性,如下所示,但我不确定这是否适用于
TestServer
:

System.Net.ServicePointManager.DefaultConnectionLimit = 100;

话虽如此,我认为使用单元测试进行负载测试并不是一个好方法,建议研究特定于负载测试的工具。


0
投票

我的测试发现了问题。
这不是测试服务器或客户端代码,而是数据库代码。

在我的控制器中,我正在启动一个 NHibernate 事务,这会阻塞请求,因为它会锁定正在更新的表。

这是正确的,所以我必须稍微更改我的代码才能不自动启动交易。而是将其留给调用代码来管理。

© www.soinside.com 2019 - 2024. All rights reserved.