创建一个模拟的IHttpFilter来测试Windows.Web.Http.HttpClient

本文关键字:测试 Windows Web HttpClient Http IHttpFilter 模拟 一个 创建 | 更新日期: 2023-09-27 18:34:26

我想创建一个"模拟"IHttpFilter实现,用于测试Windows.Web.Http HttpClient调用。这是我在实现中的发送请求异步方法

 public IAsyncOperationWithProgress<HttpResponseMessage,HttpProgress> 
    SendRequestAsync(HttpRequestMessage request)
            {
                HttpResponseMessage response = new HttpResponseMessage(_statusCode);
                response.Content = _content;
                //This is the problematic part
                return AsyncInfo.Run<HttpResponseMessage, HttpProgress>(
                    (token, progress) => Task.Run<HttpResponseMessage>(
                        () => { return response; }));           
            }

在我的测试方法中,我是这样使用它的。这也是在应用程序中使用HttpClient的方式。

//This Throws an InvalidCastException
var result = await client.SendRequestAsync(new HttpRequestMessage(HttpMethod.Get, new Uri("http://www.nomatter.com")));

但它抛出了一个 InvalidCastException

Result Message: Test method UnitTestLibrary1.UnitTest.TestHttp threw exception: 
System.InvalidCastException: Specified cast is not valid.
Result StackTrace:  
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at UnitTestLibrary1.UnitTest.<TestHttp>d__0.MoveNext() in c:'Users'****'UniversalPCLUnitTest'UnitTestLibrary1'UnitTest1.cs:line 40
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()

我无法找出为什么会抛出异常。有没有人遇到同样的问题??

创建一个模拟的IHttpFilter来测试Windows.Web.Http.HttpClient

这个问题有两个答案。

第一个答案是,你甚至不应该尝试模拟一个System.Net.HttpClient。此类应在应用中实例化一次,可能作为单一实例。

您通常会将HttpClient的使用包装到某种合约中,即IE

public interface ICanGetHttpBodies{
    string AsString(Uri uri);
}

然后,当然,使用该合约,并在需要时模拟它:

[TestMethod, ExpectedException(typeof(ProgramException))]
public void MyMethod_WhenEmptyBody_ThrowsException()
{
    // Arrange 
    var emptyBody = "";
    var getBodyMock = new Mock<ICanGetHttpBodies>()
        .Setup(m => m.AsString(It.IsAny<Uri>())
        .Returns(emptyBody);
    // Act & Assert
}

这样,您就可以完全控制代码流,将HttpClient隐藏在赋予您含义的合约中(ICanGetHttpBodies),这也使代码更易于阅读(免费奖金:)

第二个答案是,Visual Studio中有一种叫做"Fakes"的东西,它可以让你能够存根/模拟静态库,如HttpClient和DateTime:

https://msdn.microsoft.com/en-us/library/hh549175.aspx

希望这些对您有所帮助,并且您更喜欢答案选项 1 :)