Как мне посмеяться над заглушкой HttpRequestMessage в .NET Core? - PullRequest
2 голосов
/ 02 апреля 2019

У меня есть функция, которую я портирую из Azure Functions v1 в v2, и как часть этого я столкнулся с проблемой обновления моих модульных тестов, которые создают заглушенный HttpRequestMessage.Вот код, который работает с функциями v1 и предназначен для .NET Framework 4.7

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>

И это csproj для моего тестового проектапосле ретаргетинга на .NET Core 2.0

<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>

Ранее я использовал ответы на этот вопрос , чтобы правильно отключить 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 , как былосделано в этом вопросе

request.Properties.Add(nameof(HttpContext), new DefaultHttpContext());

Но это привело меня к другой ошибке (такой же, как в вопросе)

System.ArgumentNullException: значение не может быть нулевым.

Имя параметра: поставщик

1 Ответ

7 голосов
/ 02 апреля 2019

Функции Azure в некоторой степени основаны на ASP.NET MVC WebApi, в котором произошли некоторые изменения для .NET Core.Например, HttpConfiguration не доступен ни в одном из пакетов, предназначенных для .NET Core / Standard.Чтобы это исправить, мне пришлось установить несколько пакетов в моем проекте test , а именно Microsoft.AspNetCore.Mvc для AddMvc() и Microsoft.AspNetCore.Mvc.WebApiCompatShim для .AddWebApiConventions(), что:

Обеспечивает совместимость в 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, отсутствовали(что в данном случае я считаю MediaTypeFormatters), мне пришлось по существу загрузить 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\""));
}

И это заставляет тест компилироваться, запускаться и проходить.

...