模拟 HttpRequestException 进行单元测试
本文关键字:单元测试 HttpRequestException 模拟 | 更新日期: 2023-09-27 18:04:03
我有一个从网上下载大量pdf的应用程序。有时,我会收到一个 HttpRequestException,其中包含消息:将内容复制到流时出错。
因此,我正在尝试对我的代码进行单元测试以处理这种情况。我目前的下载代码是:
var request = await httpClient.GetAsync(url);
// This is where the exception would be thrown
await request.Content.ReadAsByteArrayAsync());
现在我正在尝试模拟 HttpRequestException,以便我可以对上面的代码进行单元测试,但我不知道该怎么做。谁能帮忙?
提前感谢!
这里的关键是创建一个引发异常的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
外的"不可能"(
使用 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;
}
}