我有一个要从Azure Functions v1移植到v2的函数,并且作为其中一部分,我遇到了更新我的单元测试(创建存根的HttpRequestMessage)的问题。以下是针对.NET Framework 4.7的Functions v1上可用的代码
public class FunctionExample
{
[FunctionName(nameof(SomeFunction))]
public static async Task<HttpResponseMessage> SomeFunction
(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "SomeFunction")]
HttpRequestMessage request
)
{
var body = await request.Content.ReadAsStringAsync();
if (string.IsNullOrEmpty(body))
{
return request.CreateResponse(HttpStatusCode.BadRequest, "Bad job");
}
else
{
return request.CreateResponse(HttpStatusCode.OK, "Good job");
}
}
}
我的测试代码
public class FunctionExampleTests
{
[Test]
public async Task TestSomeFunction()
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("http://localhost/"),
Content = new StringContent("", Encoding.UTF8, "application/json")
};
request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey,
new HttpConfiguration());
var response = await FunctionExample.SomeFunction(request);
var content = await response.Content.ReadAsStringAsync();
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
Assert.That(content, Is.EqualTo("\"Bad job\""));
}
}
移植到v2后,我的功能项目csproj
文件如下所示。唯一的区别是,我不再针对完整框架,并添加了AzureFunctionsVersion
节点。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AzureFunctionsVersion>v2</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.24" />
</ItemGroup>
</Project>
这是我重新定位到.NET Core 2.0之后的测试项目的csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nunit" Version="3.11.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FunctionExample\FunctionExample.csproj" />
</ItemGroup>
</Project>
以前,我使用的是this question的答案来正确地存根HttpRequestMessage,但是似乎不再起作用。
当我尝试对此进行编译时,出现以下编译错误
Error CS0246 The type or namespace name 'HttpConfiguration' could not be found (are you missing a using directive or an assembly reference?)
Error CS0103 The name 'HttpPropertyKeys' does not exist in the current context
因此,如果我只删除该行,希望不再需要该修补程序
request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
相反,我收到此错误消息
System.InvalidOperationException:HttpRequestMessage实例未正确初始化。使用HttpRequestMessageHttpContextExtensions.GetHttpRequestMessage为当前请求创建HttpRequestMessage。
尝试遵循错误消息的指示对我而言并不奏效,我尝试设置HttpContext
like was done in this question
request.Properties.Add(nameof(HttpContext), new DefaultHttpContext());
但这给了我一个不同的错误(与问题相同)
System.ArgumentNullException:值不能为null。
参数名称:provider
答案 0 :(得分:5)
Azure函数在某种程度上基于ASP.NET MVC WebApi,它对.NET Core进行了一些更改。例如,HttpConfiguration
在面向.NET Core / Standard的任何程序包中似乎均不可用。为了解决此问题,我必须在我的 test 项目中安装几个软件包,即AddMvc()
的{{3}}和.AddWebApiConventions()
的{{3}} ,
提供ASP.NET Core MVC与ASP.NET Web API 2的兼容性,以简化现有Web API实现的迁移。
所以我将它们添加到了测试项目中
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.2.0" />
现在我的测试项目看起来像这样
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nunit" Version="3.11.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.2.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FunctionExampleFunction\FunctionExampleFunction.csproj" />
</ItemGroup>
</Project>
要模拟ArgumentNullException
所暗示的服务丢失(在这种情况下,我认为是MediaTypeFormatter),我必须从本质上引导MVC来正确初始化HttpContext。
[Test]
public async Task TestSomeFunction()
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("http://localhost/"),
Content = new StringContent("", Encoding.UTF8, "application/json")
};
var services = new ServiceCollection()
.AddMvc()
.AddWebApiConventions()
.Services
.BuildServiceProvider();
request.Properties.Add(nameof(HttpContext), new DefaultHttpContext
{
RequestServices = services
});
var response = await FunctionExample.SomeFunction(request);
var content = await response.Content.ReadAsStringAsync();
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
Assert.That(content, Is.EqualTo("\"Bad job\""));
}
这使得测试可以编译,运行和通过。