我有一个web 2 web服务获取方法。在内部,我使用HttpContext.Current.Request.UserHostAddress。当直接调用我的控制器方法时,单元测试没有填写,带有空对象的错误也没有填写。因此,我搜索了如何填写这个问题,并找到了以下帮助解决该问题的方法:向HttpRequestMessage添加IP地址
但是,这需要一个服务器名来发送请求。问题是,当测试运行时,VSExpress将需要为这个API服务运行,而不仅仅是在运行测试时。最重要的是,即使它是,它似乎选择一个随机端口运行,所以我不能硬编码地址,就像他在上面的链接。鉴于上述问题,我如何测试我的api 2方法?
当我测试api方法时,这一行就会爆炸。
string ip = HttpContext.Current.Request.UserHostAddress;编辑答案
让每个人都知道这是代码中的解决方案
public class MyController : ApiController
{
private: HttpRequestBase httpRequest;
public MyController()
{
httpRequest = new HttpRequestWrapper(HttpContext.Current.Request)
}
public MyController(HttpRequestBase http)
{
httpRequest = http;
}
public HttpResponseMessage Get()
{
string ip = httpRequest.UserHostAddress;
}
}我在单元测试中使用Moq:
Mock<HttpRequestBase> httpRequestMock = new Mock<HttpRequestBase>();
httpRequestMock.Setup(x => x.UserHostAddress).Returns("127.0.0.1");
// then pass httpRequestMock.Object to my controller ctor and good to go发布于 2014-09-19 15:40:28
将对HttpContext的引用替换为对HttpContextBase的引用。在代码中,使用HttpContextBase实例初始化HttpContextWrapper,这是web堆栈中的默认行为实现。
然而,在您的测试中,注入一个自定义HttpContextBase实现,其中您只实现测试所需的方法和行为。
如链接中所述:
HttpContextBase类是一个抽象类,它包含与HttpContext类相同的成员。HttpContextBase类使您能够创建类似于HttpContext类的派生类,但可以自定义并在ASP.NET管道之外工作。在执行单元测试时,通常使用派生类来实现具有自定义行为的成员,以满足所测试的场景。
发布于 2014-09-19 15:39:46
将控制器与HTTP上下文分离。这里可能有一些我不熟悉的内置功能,但是一种方法是简单地注入一个可模拟的对象。考虑一下这样的事情:
public interface IRequestInformation
{
string UserHostAddress { get; }
}
public class RequestInformation : IRequestInformation
{
public string UserHostAddress
{
get { return HttpContext.Current.Request.UserHostAddress; }
}
}现在,您已经抽象了接口后面对HttpContext的依赖关系。如果使用依赖项注入,则将该接口插入到控制器中。如果你不是,你可以假装:
// in your controller...
private IRequestInformation _request;
public IRequestInformation RequestInfo
{
get
{
if (_request == null)
_request = new RequestInformation();
return _request;
}
set { _request = value; }
}然后在控制器逻辑中使用它:
string ip = RequestInfo.UserHostAddress;现在,在单元测试中,您可以为RequestInfo属性提供一个模拟/假/等等。要么手动创建一个,要么使用模拟库。如果手动创建一个,这就足够简单了:
public class RequestInformationFake : IRequestInformation
{
public string UserHostAddress
{
get { return "some known value"; }
}
}然后,在安排测试时,只需将其提供给控制器:
var controller = new YourController();
controller.RequestInformation = new RequestInformationFake();
// run your test发布于 2020-05-22 02:35:02
将下列方法添加到控制器中,或注入等效的方法。它使用神奇的字符串MS_HttpContext,因为这正是AspNetWebStack 实现所使用的完全相同的目的。
HttpContextBase HttpContextBase => HttpContext.Current != null
? new HttpContextWrapper(HttpContext.Current)
: (HttpContextBase)Request.Properties["MS_HttpContext"]将控制器中HttpContext.Current的所有其他用途替换为HttpContextBase。
当单元测试:
var context = new Mock<HttpContextBase>();
...
controller.Request = new HttpRequestMessage();
controller.Request.Properties["MS_HttpContext"] = context.Object;https://stackoverflow.com/questions/25937456
复制相似问题