我有一个从网上下载大量pdf的应用程序。有时,我得到一个HttpRequestException,包含消息:将内容复制到流时出错。
所以,我正在尝试对我的代码进行单元测试以处理这种情况。我目前的下载代码是:
var request = await httpClient.GetAsync(url);
// This is where the exception would be thrown
await request.Content.ReadAsByteArrayAsync());
现在我正在尝试模拟HttpRequestException,以便我可以对上面的代码进行单元测试,但我不知道该怎么做。有人可以帮忙吗?
提前致谢!
答案 0 :(得分:2)
这里的关键是创建一个抛出异常的HttpContent
:
public class ExceptionThrowingContent : HttpContent
{
private readonly Exception exception;
public ExceptionThrowingContent(Exception exception)
{
this.exception = exception;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
return Task.FromException(exception);
}
protected override bool TryComputeLength(out long length)
{
length = 0L;
return false;
}
}
完成后,您可以使用我自己的mockhttp之类的东西来模拟请求:
var handler = new MockHttpMessageHandler();
handler.When("http://tempuri.org/url")
.Respond(new ExceptionThrowingContent(ex));
var mockClient = new HttpClient(handler);
// pass mockHandler to your component
现在,如果您的组件在发出请求时传入HttpCompletionOption.ResponseHeadersRead
,则会在await Content.ReadAsByteArrayAsync()
处抛出异常。如果没有,HttpClient将尝试缓冲响应,以便在await HttpClient.GetAsync()
抛出异常。
如果响应 被缓冲,那么在ReadAsByteArrayAsync
抛出异常实际上是“不可能的”,因此尝试模拟它是没有意义的。 (OutOfMemoryException
之外的“不可能”)
答案 1 :(得分:1)
使用MockHttp可以轻松地设置HttpClient
测试,您可以返回自定义的HttpContent
,在此示例中会抛出HttpRequestException
。
[TestMethod]
[ExpectedException(typeof(HttpRequestException))]
public async Task Test()
{
var content = new ContentWithException();
var mockHttp = new MockHttpMessageHandler();
mockHttp.Expect("http://localhost/mypdfDownload").Respond(content);
var client = new HttpClient(mockHttp);
var response = await client.GetAsync("http://localhost/mypdfDownload");
await response.Content.ReadAsByteArrayAsync();
}
private class ContentWithException : HttpContent
{
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
throw new HttpRequestException();
}
protected override bool TryComputeLength(out long length)
{
length = 0;
return false;
}
}