将我的API从ASP.Net Core 2.1升级到2.2之后,我在运行时遇到了InvalidOperationException异常。
呼叫堆栈
System.InvalidOperationException:
at Microsoft.AspNetCore.Mvc.CreatedAtActionResult.OnFormatting (Microsoft.AspNetCore.Mvc.Core, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsync (Microsoft.AspNetCore.Mvc.Core, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at Microsoft.AspNetCore.Mvc.ObjectResult.ExecuteResultAsync (Microsoft.AspNetCore.Mvc.Core, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeResultAsync>d__20.MoveNext (Microsoft.AspNetCore.Mvc.Core, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
原因
这是由于我的CreatedAtAction中缺少参数所致。
public async Task<IActionResult> GetFields([FromRoute]Guid productId)
{
return Ok(await _prodRepo.GetProductFields(productId));
}
public async Task<IActionResult> CreateFields([FromRoute]Guid productId, [FromBody]ProductField[] fields)
{
...
return CreatedAtAction(nameof(GetFields), fields);
}
解决方案
最后一行应该包含productId
路由值,如下所示:
return CreatedAtAction(nameof(GetFields), { productId }, fields);
当路由值名称不匹配时,会发生相同的错误。它并没有在2.1中引起运行时异常,但是我猜想它对依赖返回URL的任何人都是无声的。
更大的问题
如果路由值的名称不正确,则会在运行时发生相同的异常。代码编译时没有错误也没有警告,并且在运行时失败。
我担心的是,这些错误在开发过程中很容易引入,并且很容易遗漏,并且仅在运行时浮出水面。我们有一个开发人员团队积极从事此Web API项目。当一个动作方法的签名更改时,会再次发生(从另一个动作的CreatedAtAction
结果中引用)。
如何对这种错误情况进行单元测试?我不想在部署之前必须在所有API端点上运行集成测试来捕获运行时错误。
尝试
我尝试了以下操作,但随后发现我需要一个UrlHelper并卡在此处。
[Fact]
public void Test_CreateFields_CreatedAtAction_Values()
{
var fields = new ProductFieldRel { ProductId = _productId };
var task = _controller.CreateFields(_productId, new[] { fields });
var result = task.Result as CreatedAtActionResult;
Assert.NotNull(result);
result.OnFormatting(new ControllerContext
{
HttpContext = new DefaultHttpContext { User = _user }
});
}