模拟 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,以便我可以对上面的代码进行单元测试,但我不知道该怎么做。谁能帮忙?

提前感谢!

模拟 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;
    }
}