gpt4 book ai didi

c# - 是否可以模拟 .NET HttpWebResponse?

转载 作者:IT王子 更新时间:2023-10-29 03:44:30 28 4
gpt4 key购买 nike

我有一个集成测试,它从第 3 方服务器获取一些 json 结果。它真的很简单而且效果很好。

我希望停止实际攻击此服务器并使用 Moq(或任何 Mocking 库,如 ninject 等)劫持并强制返回结果。

这可能吗?

这是一些示例代码:-

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..
}

当然,这个方法是从我的测试中调用的。

我当时在想,也许我需要将模拟的 httpWebResponse 或其他东西传递给此方法(或类的属性?),但不太确定是否是这种方式。此外,响应是 httpWebRequest.GetResponse() 方法的输出。所以也许我只需要传入一个模拟的 HttpWebRequest

任何关于示例代码的建议都非常感谢!

最佳答案

您可能希望更改您的消费代码以接受一个工厂接口(interface),该工厂创建请求和响应,这些请求和响应可以被模拟并包装实际实现。

更新:重温

在我的回答被接受后很久,我就一直收到反对票,我承认我原来的回答质量很差,并且做出了很大的假设。

在 4.5+ 中模拟 HttpWebRequest

我原来的答案的困惑在于您可以在 4.5 中模拟 HttpWebResponse,但不能模拟更早的版本。在 4.5 中模拟它也使用过时的构造函数。因此,推荐的做法是抽象请求和响应。不管怎样,下面是使用 .NET 4.5 和 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):

[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();
}
}

关于c# - 是否可以模拟 .NET HttpWebResponse?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9823039/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com