如何在 .NET API Controller 中正确模拟长 运行 进程
How to simulate long running process in .NET API Controller Correctly
我正在尝试创建一个单元测试来模拟我的 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();
您可以使用 Task.Delay(time in milliseconds)
。 Thread.Sleep
不会释放线程,在等待结果时无法处理其他任务。
默认情况下,.NET 中的 HttpClient
class 对同一服务器的两个并发请求有限制,我认为这可能是导致此问题的原因。通常,可以通过创建一个新的 HttpClientHandler
并将其用作构造函数中的参数来覆盖此限制:
new HttpClient(new HttpClientHandler
{
MaxConnectionsPerServer = 100
})
但是因为客户端是使用 TestServer
方法创建的,所以会变得有点复杂。您可以尝试像下面那样更改 ServicePointManager.DefaultConnectionLimit
属性,但我不确定这是否适用于 TestServer
:
System.Net.ServicePointManager.DefaultConnectionLimit = 100;
话虽如此,我认为使用单元测试进行负载测试并不是一个好方法,建议研究特定于负载测试的工具。
我发现我的测试有问题。
不是 TestServer 或客户端代码,而是数据库代码。
在我的控制器中,我启动了一个 NHibernate 事务,这阻止了请求,因为它会锁定正在更新的 table。
这是正确的,所以我不得不稍微更改我的代码以不自动启动交易。而是将其留给调用代码来管理。
我正在尝试创建一个单元测试来模拟我的 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();
您可以使用 Task.Delay(time in milliseconds)
。 Thread.Sleep
不会释放线程,在等待结果时无法处理其他任务。
默认情况下,.NET 中的 HttpClient
class 对同一服务器的两个并发请求有限制,我认为这可能是导致此问题的原因。通常,可以通过创建一个新的 HttpClientHandler
并将其用作构造函数中的参数来覆盖此限制:
new HttpClient(new HttpClientHandler
{
MaxConnectionsPerServer = 100
})
但是因为客户端是使用 TestServer
方法创建的,所以会变得有点复杂。您可以尝试像下面那样更改 ServicePointManager.DefaultConnectionLimit
属性,但我不确定这是否适用于 TestServer
:
System.Net.ServicePointManager.DefaultConnectionLimit = 100;
话虽如此,我认为使用单元测试进行负载测试并不是一个好方法,建议研究特定于负载测试的工具。
我发现我的测试有问题。
不是 TestServer 或客户端代码,而是数据库代码。
在我的控制器中,我启动了一个 NHibernate 事务,这阻止了请求,因为它会锁定正在更新的 table。
这是正确的,所以我不得不稍微更改我的代码以不自动启动交易。而是将其留给调用代码来管理。