azz*_*ack 7 asp.net asynchronous mongodb asp.net-web-api mongodb-.net-driver
今天我在使用异步ApiControllers创建Web API时遇到了问题.我正在使用MongoDB,因为C#驱动程序不支持异步,我尝试在我的存储库层实现它.
构建存储库中生成的方法如下所示:
public async Task<IEnumerable<Building>> GetAll()
{
var tcs = new TaskCompletetionSource<IEnumerable<Building>>();
await Task.Run(() => {
var c = this.MongoDbCollection.FindAll();
tcs.SetResult(c);
});
return await tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)
现在,当使用NUnit自行测试存储库时,这非常有效.
但是当从控制器进行测试时(使用HttpClient),它在运行后永远不会进入"返回"线tcs.SetResult(c).测试一直运行,直到我手动中止.
当我删除Task.Run代码并同步执行所有操作时,一切都按预期工作:
public async Task<IEnumerable<Building>> GetAll()
{
var c = this.MongoDbCollection.FindAll();
return c;
}
Run Code Online (Sandbox Code Playgroud)
有没有人知道为什么我在测试存储库+数据库和测试控制器+存储库+数据库时遇到不同的行为?
的控制器的方法是这样的:(buildingRepository在使用Ninject构造注入)
public async Task<HttpResponseMessage> Get()
{
var result = await this.buildingRepository.GetAll();
return Request.CreateResponse(HttpStatusCode.OK, result);
}
Run Code Online (Sandbox Code Playgroud)
编辑:这里也是测试方法.第一个是不工作的那个:( this.client是一个设置了accept-header的HttpClient对象"application/json")
[Test]
public void Get_WhenBuildingsExist_ShouldReturnBuilding()
{
var task = this.client.GetAsync("/api/building/");
var result = task.Result.Content.ReadAsStringAsync().Result;
var o = JsonConvert.DeserializeObject<IEnumerable<Building>>(result);
Assert.That(o.Any());
}
[Test]
public void Get_WhenBuildingsExist_ShouldReturnAtLeastOneBuilding()
{
var buildings = this.buildingRepository.GetAll().Result;
Assert.That(buildings.Any());
}
Run Code Online (Sandbox Code Playgroud)
最好的选择是升级到支持异步单元测试的 NUnit 版本,并将所有Result/Wait调用更改为await:
[Test]
public async Task Get_WhenBuildingsExist_ShouldReturnBuilding()
{
var content = await this.client.GetAsync("/api/building/");
var result = await content.ReadAsStringAsync();
var o = JsonConvert.DeserializeObject<IEnumerable<Building>>(result);
Assert.That(o.Any());
}
Run Code Online (Sandbox Code Playgroud)
如果这是不可能的(例如,在撰写本文时,Xamarin 仍然运行非常旧版本的 NUnit),那么您可以使用AsyncContext我的 AsyncEx 库:
[Test]
public void Get_WhenBuildingsExist_ShouldReturnBuilding()
{
var o = AsyncContext.Run(async () =>
{
var content = await this.client.GetAsync("/api/building/");
var result = await content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<IEnumerable<Building>>(result);
});
Assert.That(o.Any());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1202 次 |
| 最近记录: |