У нас есть следующий код ASP.NET (я сократил его для ясности):
var httpContent = new StringContent(postData, Encoding.UTF8);
using (var client = this.GetClient(url, contentType))
{
using (var response = await client.PostAsync(url, httpContent).ConfigureAwait(true);
{
ret.Response = await response.Content.ReadAsStringAsync().ConfigureAwait(true);
}
}
'client' - это объект HttpClient при запуске в PROD, но в нашем модульном тесте это:
MockRepository.GenerateMock<IHttpClient>();
Обратите внимание, что мы используем .ConfigureAwait (true) . Причина этого заключается в том, что мы храним объекты в коллекции HttpContext.Current.Items (это, вероятно, не идеально, но это то, что есть). Если мы не сохранили контекст потока, то HttpContext.Current возвращается как ноль.
Это все работает как положено при запуске в PROD.
Однако при запуске модульного теста выполнение следующей строки теряет Context и HttpContext.Current становится равным нулю:
await response.Content.ReadAsStringAsync().ConfigureAwait(true);
Примечание. Исходящий вызов PostAsync для заглушки поддерживает контекст.
Так, как мы программируем заглушку?
using (var httpResponse = new HttpResponseMessage())
{
httpResponse.Content = new StringContent(msg, Encoding.UTF8);
httpResponse.StatusCode = HttpStatusCode.OK;
this.FakeHttpClient
.Stub(i => i.PostAsync("", "")).IgnoreArguments()
.Return(Task.FromResult(this.httpResponse)).Repeat.Once();
// Act
}
Когда тест запускается, данные возвращаются, поэтому поддельные объекты ведут себя идеально, ЗА ИСКЛЮЧЕНИЕМ того, что ReadAsStringAsync (). ConfigureAwait (true) разрушает контекст.
StringContent не может быть смоделирован напрямую, так как не имеет конструктора без параметров. Я создал класс-обертку, чтобы посмотреть, смогу ли я это высмеять, но когда у меня был следующий код:
var fakeStringContent = MockRepository.GenerateStub<Wrap>();
fakeStringContent
.Stub(fsc => fsc.ReadAsStringAsync())
.Return(Task.FromResult("<response/>"))
.Repeat.Once();
Затем в строку .Stub (...) было выдано исключение, которое было:
System.InvalidOperationException: 'Асинхронная операция не вернулась
объект System.Threading.Tasks.Task. '