使用 HttpRequestMessage 对 Azure Functions 进行单元测试
Posted
技术标签:
【中文标题】使用 HttpRequestMessage 对 Azure Functions 进行单元测试【英文标题】:Unit Testing Azure Functions with HttpRequestMessage 【发布时间】:2018-09-04 23:51:45 【问题描述】:尝试在 Visual Studio 中对 HTTP Trigger Azure Functions 进行单元测试时遇到了一些问题。我创建了一个 GitHub 存储库 (https://github.com/ericdboyd/TestingAzureFunctions),其中包含一个示例解决方案,其中包含一个 Azure Function 项目和一个演示问题的单元测试项目。
首先,当我引入 Microsoft.AspNet.WebApi.Core 时,它会在尝试使用 IContentNegotiator 时在 System.Web.Http 和 Microsoft.AspNetCore.Mvc.WebApiCompatShim 之间产生冲突。解决这个问题的唯一方法是使用以下代码在测试项目的 csproj 文件中为 WebApiCompatShim 设置别名:
<Target Name="ChangeAliasesOfStrongNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
<ItemGroup>
<ReferencePath Condition="'%(FileName)' == 'Microsoft.AspNetCore.Mvc.WebApiCompatShim'">
<Aliases>webapicompatshim</Aliases>
</ReferencePath>
</ItemGroup>
一旦我克服了那个错误,我就会遇到这个我无法克服的问题。使用 HttpRequestMessage.CreateResponse 扩展方法在 Azure 函数中返回响应,我得到“没有为类型 'System.Net.Http.Formatting.IContentNegotiator' 注册的服务。”当我尝试测试它时。我尝试构建一个 HttpRequestMessage ,我认为它应该使用以下代码与该扩展方法一起使用,该代码也可以在 GitHub 存储库中找到,但它失败了,我已经努力尝试通过这个几个小时了。
IServiceCollection services = new ServiceCollection();
services.AddOptions();
services.AddSingleton(typeof(IContentNegotiator), typeof(DefaultContentNegotiator));
IServiceProvider serviceProvider = services.BuildServiceProvider();
var httpContext = new DefaultHttpContext RequestServices = serviceProvider;
var httpConfiguration = new HttpConfiguration();
HttpRequestMessage request = new HttpRequestMessage
Method = HttpMethod.Post,
RequestUri = new Uri(url),
Content = new StringContent(content, Encoding.UTF8, "application/json"),
Properties =
HttpPropertyKeys.HttpConfigurationKey, httpConfiguration ,
nameof(HttpContext), httpContext
;
如果我不使用 CreateResponse 扩展方法,而只创建 HttpResponseMessage 对象,它就可以正常工作。
只是为了设置一些额外的上下文,我知道这不是对 Azure 函数正在执行的代码进行单元测试的最佳方法。我正在更细致地对该代码进行单元测试。但我希望能够对执行 http 请求和对该逻辑的响应之间的映射的 Azure 函数进行单元测试。
GitHub repo 中有两个 Azure Functions 和两个单元测试,一组带有扩展方法,一组没有演示问题。但其他一切都一样。
【问题讨论】:
【参考方案1】:在响应时指定 jsonformatter,如下所示
req.CreateResponse(HttpStatusCode.OK, $"Hello, name", new JsonMediaTypeFormatter())
【讨论】:
【参考方案2】:不能直接回答您的问题,但应该可以帮助您继续前进。
您使用的是 Azure Functions v2 - .NET Standard 版本。这个版本目前处于测试阶段,所以它有点阴暗:文档丢失并且存在一些问题。
在 V2 中,建议您使用 HttpRequest
类和 IActionResult
而不是“经典”HttpRequestMessage
和 HttpResponseMessage
。默认模板的签名如下:
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req, TraceWriter log)
这应该使您能够摆脱 shim 并对类似于 ASP.NET Core 方式的功能进行单元测试。
【讨论】:
以上是关于使用 HttpRequestMessage 对 Azure Functions 进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章
如何全局访问当前的 HttpRequestMessage 对象?
使用 HttpRequestMessage 或 Stream 上传 REST 文件?
HttpClient 标头与 HttpRequestMessage 标头
c# 如何正确传递 HttpRequestMessage 并在函数外返回 HttpRequestMessage 而不会泄漏
如何从 HttpRequestMessage 中获取方法名称?
HttpRequestMessage.GetClientCertificate() 在 Web API 中返回 null