是否可以模拟出一个.NET HttpWebResponse? [英] Is it possible to mock out a .NET HttpWebResponse?

查看:179
本文介绍了是否可以模拟出一个.NET HttpWebResponse?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个集成测试,抓住从第三方服务器的一些JSON结果。这是非常简单和伟大工程。

i've got an integration test that grabs some json result from a 3rd party server. It's really simple and works great.

我希望停止实际上达不到这个服务器,并使用起订量(或任何嘲讽库,就像ninject等),以劫持并迫使返回结果。

I was hoping to stop actually hitting this server and using Moq (or any Mocking library, like ninject, etc) to hijack and force the return result.

这可能吗?

下面是一些示例code: -

Here is some sample code :-

public Foo GoGetSomeJsonForMePleaseKThxBai()
{
    // prep stuff ...

    // Now get json please.
    HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("Http://some.fancypants.site/api/hiThere);
    httpWebRequest.Method = WebRequestMethods.Http.Get;

    string responseText;

    using (var httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse())
    {
        using (var streamReader = new StreamReader(httpWebResponse.GetResponseStream()))
        {
            json = streamReader.ReadToEnd().ToLowerInvariant();
        }
    }

    // Check the value of the json... etc..
}

当然,

和,这种方法是从我的测试调用。

and of course, this method is called from my test.

我在想,也许我需要通过这个方法(或类的属性?)一个嘲笑 httpWebResponse 或东西,但不太清楚,如果这是的方式。此外,响应从 httpWebRequest.GetResponse()方法的输出..所以也许我只是需要传递一个嘲笑的HttpWebRequest

I was thinking that maybe I need to pass into this method (or a property of the class?) a mocked httpWebResponse or something but wasn't too sure if this was the way. Also, the response is a output from an httpWebRequest.GetResponse() method .. so maybe I just need to pass in a mocked HttpWebRequest ?.

一些样品code的任何建议将最aprreciated!

any suggestions with some sample code would be most aprreciated!

推荐答案

您可能想改变你的消费code采取一个接口的工厂,创建请求和响应,可以嘲笑它包装的实际执行情况

You may wish to change your consuming code to take in an interface for a factory that creates requests and responses that can be mocked which wrap the actual implementation.

我已经得到downvotes不久之后我的回答被接受了,我承认我原来的答复是质量差,取得了很大的假设。

I've been getting downvotes long after my answer was accepted, and I admit my original answer was poor quality and made a big assumption.

这是我原来的答复的困惑在于,你可以嘲笑 HttpWebResponse 4.5,而不是早期版本。嘲笑它在4.5还采用过时的构造函数。因此,操作的建议当然是抽象的请求和响应。不管怎样,下面是一个使用.NET 4.5与4.2 Moq的一个完整的工作测试。

The confusion from my original answer lies in the fact that you can mock HttpWebResponse in 4.5, but not earlier versions. Mocking it in 4.5 also utilizes obsolete constructors. So, the recommended course of action is to abstract the request and response. Anyways, below is a complete working test using .NET 4.5 with Moq 4.2.

[Test]
public void Create_should_create_request_and_respond_with_stream()
{
    // arrange
    var expected = "response content";
    var expectedBytes = Encoding.UTF8.GetBytes(expected);
    var responseStream = new MemoryStream();
    responseStream.Write(expectedBytes, 0, expectedBytes.Length);
    responseStream.Seek(0, SeekOrigin.Begin);

    var response = new Mock<HttpWebResponse>();
    response.Setup(c => c.GetResponseStream()).Returns(responseStream);

    var request = new Mock<HttpWebRequest>();
    request.Setup(c => c.GetResponse()).Returns(response.Object);

    var factory = new Mock<IHttpWebRequestFactory>();
    factory.Setup(c => c.Create(It.IsAny<string>()))
        .Returns(request.Object);

    // act
    var actualRequest = factory.Object.Create("http://www.google.com");
    actualRequest.Method = WebRequestMethods.Http.Get;

    string actual;

    using (var httpWebResponse = (HttpWebResponse)actualRequest.GetResponse())
    {
        using (var streamReader = new StreamReader(httpWebResponse.GetResponseStream()))
        {
            actual = streamReader.ReadToEnd();
        }
    }


    // assert
    actual.Should().Be(expected);
}

public interface IHttpWebRequestFactory
{
    HttpWebRequest Create(string uri);
}

更好的答案:抽象的响应和请求

下面是一个更安全的骨架实现,将事先版本一起使用一种抽象的(当然,下降到3.5至少):

Better answer: Abstract the Response and Request

Here's a safer bare-bones implementation of an abstraction that will work for prior versions (well, down to 3.5 at least):

[Test]
public void Create_should_create_request_and_respond_with_stream()
{
    // arrange
    var expected = "response content";
    var expectedBytes = Encoding.UTF8.GetBytes(expected);
    var responseStream = new MemoryStream();
    responseStream.Write(expectedBytes, 0, expectedBytes.Length);
    responseStream.Seek(0, SeekOrigin.Begin);

    var response = new Mock<IHttpWebResponse>();
    response.Setup(c => c.GetResponseStream()).Returns(responseStream);

    var request = new Mock<IHttpWebRequest>();
    request.Setup(c => c.GetResponse()).Returns(response.Object);

    var factory = new Mock<IHttpWebRequestFactory>();
    factory.Setup(c => c.Create(It.IsAny<string>()))
        .Returns(request.Object);

    // act
    var actualRequest = factory.Object.Create("http://www.google.com");
    actualRequest.Method = WebRequestMethods.Http.Get;

    string actual;

    using (var httpWebResponse = actualRequest.GetResponse())
    {
        using (var streamReader = new StreamReader(httpWebResponse.GetResponseStream()))
        {
            actual = streamReader.ReadToEnd();
        }
    }


    // assert
    actual.Should().Be(expected);
}

public interface IHttpWebRequest
{
    // expose the members you need
    string Method { get; set; }

    IHttpWebResponse GetResponse();
}

public interface IHttpWebResponse : IDisposable
{
    // expose the members you need
    Stream GetResponseStream();
}

public interface IHttpWebRequestFactory
{
    IHttpWebRequest Create(string uri);
}

// barebones implementation

private class HttpWebRequestFactory : IHttpWebRequestFactory
{
    public IHttpWebRequest Create(string uri)
    {
        return new WrapHttpWebRequest((HttpWebRequest)WebRequest.Create(uri));
    }
}

public class WrapHttpWebRequest : IHttpWebRequest
{
    private readonly HttpWebRequest _request;

    public WrapHttpWebRequest(HttpWebRequest request)
    {
        _request = request;
    }

    public string Method
    {
        get { return _request.Method; }
        set { _request.Method = value; }
    }

    public IHttpWebResponse GetResponse()
    {
        return new WrapHttpWebResponse((HttpWebResponse)_request.GetResponse());
    }
}

public class WrapHttpWebResponse : IHttpWebResponse
{
    private WebResponse _response;

    public WrapHttpWebResponse(HttpWebResponse response)
    {
        _response = response;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_response != null)
            {
                ((IDisposable)_response).Dispose();
                _response = null;
            }
        }
    }

    public Stream GetResponseStream()
    {
        return _response.GetResponseStream();
    }
}

这篇关于是否可以模拟出一个.NET HttpWebResponse?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆