使用 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 而不是“经典”HttpRequestMessageHttpResponseMessage。默认模板的签名如下:

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