Подтвердить что ты не робот

Как пройти в издеваемом HttpClient в .NET-тесте?

У меня есть служба, которая использует Microsoft.Net.Http для извлечения некоторых данных Json. Отлично!

Конечно, я не хочу, чтобы мой unit test удалял фактический сервер (в противном случае это был тест интеграции).

Здесь мой сервис ctor (который использует инъекцию зависимостей...)

public Foo(string name, HttpClient httpClient = null)
{
...
}

Я не уверен, как я могу издеваться над этим... скажем.. Moq или FakeItEasy.

Я хочу убедиться, что когда мой сервис вызывает GetAsync или PostAsync.., то я могу подделать эти вызовы.

Любые предложения, как я могу это сделать?

Я -hoping- мне не нужно делать свой собственный Wrapper.. потому что это дерьмо:( Microsoft не могла сделать надзор с этим, правильно?

(да, легко сделать обертки.. я сделал их раньше... но это точка!)

4b9b3361

Ответ 1

Вы можете заменить основной HttpMessageHandler на поддельный. Что-то похожее на это...

public class FakeResponseHandler : DelegatingHandler
    {
        private readonly Dictionary<Uri, HttpResponseMessage> _FakeResponses = new Dictionary<Uri, HttpResponseMessage>(); 

        public void AddFakeResponse(Uri uri, HttpResponseMessage responseMessage)
        {
                _FakeResponses.Add(uri,responseMessage);
        }

        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            if (_FakeResponses.ContainsKey(request.RequestUri))
            {
                return _FakeResponses[request.RequestUri];
            }
            else
            {
                return new HttpResponseMessage(HttpStatusCode.NotFound) { RequestMessage = request};
            }

        }
    }

а затем вы можете создать клиента, который будет использовать поддельный обработчик.

var fakeResponseHandler = new FakeResponseHandler();
fakeResponseHandler.AddFakeResponse(new Uri("http://example.org/test"), new HttpResponseMessage(HttpStatusCode.OK));

var httpClient = new HttpClient(fakeResponseHandler);

var response1 = await httpClient.GetAsync("http://example.org/notthere");
var response2 = await httpClient.GetAsync("http://example.org/test");

Assert.Equal(response1.StatusCode,HttpStatusCode.NotFound);
Assert.Equal(response2.StatusCode, HttpStatusCode.OK);

Ответ 2

Я знаю, что это старый вопрос, но я наткнулся на него во время поиска по этой теме и нашел очень приятное решение для упрощения тестирования HttpClient.

Он доступен через nuget:

https://github.com/richardszalay/mockhttp

PM> Install-Package RichardSzalay.MockHttp

Вот краткий обзор использования:

var mockHttp = new MockHttpMessageHandler();

// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When("http://localost/api/user/*")
        .Respond("application/json", "{'name' : 'Test McGee'}"); // Respond with JSON

// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);

var response = await client.GetAsync("http://localost/api/user/1234");
// or without await: var response = client.GetAsync("http://localost/api/user/1234").Result;

var json = await response.Content.ReadAsStringAsync();

// No network connection required
Console.Write(json); // {'name' : 'Test McGee'}

Дополнительная информация о странице проекта github. Надеюсь, это может быть полезно.

Ответ 3

Я бы просто внес небольшой вклад в ответ @Darrel Miller, который использует Task.FromResult, чтобы избежать предупреждения об асинхронном методе, ожидающем оператора ожидания.

public class FakeResponseHandler : DelegatingHandler
{
    private readonly Dictionary<Uri, HttpResponseMessage> _FakeResponses = new Dictionary<Uri, HttpResponseMessage>();

    public void AddFakeResponse(Uri uri, HttpResponseMessage responseMessage)
    {
        _FakeResponses.Add(uri, responseMessage);
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        if (_FakeResponses.ContainsKey(request.RequestUri))
        {
            return Task.FromResult(_FakeResponses[request.RequestUri]);
        }
        else
        {
            return Task.FromResult(new HttpResponseMessage(HttpStatusCode.NotFound) { RequestMessage = request });
        }
    }
}

Ответ 4

Вы можете взглянуть на Microsoft Fakes, особенно в разделе Shims. С их помощью вы можете изменять поведение своего HttpClient. Предпосылкой является то, что вы используете VS Premium или Ultimate.