如何在.NET测试中传递一个模拟的HttpClient?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (37)

我有一个服务Microsoft.Net.Http用来检索一些Json数据。

当然,我不希望我的单元测试碰到实际的服务器(否则,这是一个集成测试)。

这是我的服务ctor(它使用依赖注入...)

public Foo(string name, HttpClient httpClient = null)
{
...
}

我不知道我怎么能用...说Moq或者嘲笑这个FakeItEasy

我想确保当我调用GetAsyncPostAsync..然后我可以伪造这些调用。

任何建议如何我可以做到这一点?

我是 - 希望 - 我不需要做我自己的包装..因为这是废话:(微软不能用这个疏忽,对吧?

提问于
用户回答回答于

你可以用一个假的替换核心HttpMessageHandler。看起来像这样的东西...

public class FakeResponseHandler : DelegatingHandler
    {
        private readonly Dictionary<Uri, HttpResponseMessage> _FakeResponses = new Dictionary<Uri, HttpResponseMessage>(); 

        public void AddFakeResponse(Uri uri, HttpResponseMessage responseMessage)
        {
                _FakeResponses.Add(uri,responseMessage);
        }

        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            if (_FakeResponses.ContainsKey(request.RequestUri))
            {
                return _FakeResponses[request.RequestUri];
            }
            else
            {
                return new HttpResponseMessage(HttpStatusCode.NotFound) { RequestMessage = request};
            }

        }
    }

然后可以创建一个将使用假处理程序的客户端。

var fakeResponseHandler = new FakeResponseHandler();
fakeResponseHandler.AddFakeResponse(new Uri("http://example.org/test"), new HttpResponseMessage(HttpStatusCode.OK));

var httpClient = new HttpClient(fakeResponseHandler);

var response1 = await httpClient.GetAsync("http://example.org/notthere");
var response2 = await httpClient.GetAsync("http://example.org/test");

Assert.Equal(response1.StatusCode,HttpStatusCode.NotFound);
Assert.Equal(response2.StatusCode, HttpStatusCode.OK);
用户回答回答于

我知道这是一个古老的问题,但我在搜索这个主题时偶然发现了它,并发现了一个非常好的解决方案,可以使测试HttpClient变得更加简单。

它可以通过nuget获得:

https://github.com/richardszalay/mockhttp

PM> Install-Package RichardSzalay.MockHttp

以下是对使用情况的简要介绍:

var mockHttp = new MockHttpMessageHandler();

// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When("http://localost/api/user/*")
        .Respond("application/json", "{'name' : 'Test McGee'}"); // Respond with JSON

// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);

var response = await client.GetAsync("http://localost/api/user/1234");
// or without await: var response = client.GetAsync("http://localost/api/user/1234").Result;

var json = await response.Content.ReadAsStringAsync();

// No network connection required
Console.Write(json); // {'name' : 'Test McGee'}

更多关于github项目页面的信息。希望这可以是有用的。

扫码关注云+社区