2017-01-19 4 views
4

Мы издевались над HttpMessageHandler, поэтому мы можем протестировать класс, который использует HttpClient.Проверьте значение HttpRequestMessage.Content после вызова PostAsync

Один из наших тестируемых методов создает новый HttpClient, вызывает PostAsync и располагает HttpClient. Мы хотели бы, чтобы проверить Content запроса HTTP, как это:

Assert.Equal("", ActualHttpRequestMessage.Content.ReadAsStringAsync()); 

Проблема заключается в том, что мы «не удается получить доступ к объекту, расположенную,» потому что the HttpClient disposes the Content.

Вопрос Как мы можем проверить содержание?

Это наша установка Moq.

MockHttpMessageHandler = new Mock<HttpMessageHandler>(); 

MockHttpMessageHandler 
    .Protected() 
    .Setup<Task<HttpResponseMessage>>(
     "SendAsync", 
     ItExpr.IsAny<HttpRequestMessage>(), 
     ItExpr.IsAny<CancellationToken>()) 
    .Callback<HttpRequestMessage, CancellationToken>(
     (httpRequestMessage, cancellationToken) => 
     { 
      ActualHttpRequestMessage = httpRequestMessage; 
     }) 
    .Returns(
     Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) 
     { 
      Content = new StringContent(string.Empty) 
     })); 

Так мы используем его в тестируемом классе.

new HttpClient(HttpMessageHandler); 
+0

Я не буду добавлять это в качестве ответа, так как это моя собственная библиотека, но вы посмотрели на [MockHttp] (https://github.com/richardszalay/mockhttp)? Он обеспечивает более приятную DSL для издевательских запросов HttpClient по сравнению с динамичной насмешливой библиотекой, такой как Moq. –

ответ

2

Измените свой макет к этому:

MockHttpMessageHandler 
    .Protected() 
    .Setup<Task<HttpResponseMessage>>(
     "SendAsync", 
     ItExpr.IsAny<HttpRequestMessage>(), 
     ItExpr.IsAny<CancellationToken>()) 
    .Callback<HttpRequestMessage, CancellationToken>(
     (httpRequestMessage, cancellationToken) => 
     { 
      // +++++++++++++++++++++++++++++++++++++++++ 
      // Read the Content here before it's disposed 
      ActualHttpRequestContent = httpRequestMessage.Content 
       .ReadAsStringAsync() 
       .GetAwaiter() 
       .GetResult(); 

      ActualHttpRequestMessage = httpRequestMessage; 
     }) 
    .Returns(
     Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) 
     { 
      Content = new StringContent(string.Empty) 
     })); 

Затем вы можете проверить, как это:

Assert.Equal("", ActualHttpRequestContent); 

Имейте в виду, что мы можем только читать Content один раз, так что если вы попытаетесь прочитайте его позже, он будет пустым. Это похоже на объект Гейзенберга.

+0

Это не наш метод тестирования, который удаляет контент. Это наш метод под контролем, который это делает. Наш тестируемый метод вызывает «HttpClient.PostAsync», который автоматически устанавливает «HttpResponseMessage.Content». –

+0

Мои извинения. Я думал, что вы ссылаетесь на ответное сообщение. Почему в вашем тестировании устройства необходимо проверить содержимое запроса ПОСЛЕ публикации? Осмотрите его раньше. Проводка не приведет к изменению содержимого запроса. (или - ваш модульный тест проверяет запрос, но ваш комментарий относится к ответу) – dkackman

+0

Как мы можем проверить его до публикации? –