首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#单元测试API 2调用

C#单元测试API 2调用
EN

Stack Overflow用户
提问于 2014-09-19 15:31:03
回答 3查看 2.8K关注 0票数 0

我有一个web 2 web服务获取方法。在内部,我使用HttpContext.Current.Request.UserHostAddress。当直接调用我的控制器方法时,单元测试没有填写,带有空对象的错误也没有填写。因此,我搜索了如何填写这个问题,并找到了以下帮助解决该问题的方法:向HttpRequestMessage添加IP地址

但是,这需要一个服务器名来发送请求。问题是,当测试运行时,VSExpress将需要为这个API服务运行,而不仅仅是在运行测试时。最重要的是,即使它是,它似乎选择一个随机端口运行,所以我不能硬编码地址,就像他在上面的链接。鉴于上述问题,我如何测试我的api 2方法?

当我测试api方法时,这一行就会爆炸。

代码语言:javascript
复制
string ip = HttpContext.Current.Request.UserHostAddress;

编辑答案

让每个人都知道这是代码中的解决方案

代码语言:javascript
复制
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:

代码语言:javascript
复制
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
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-09-19 15:40:28

将对HttpContext的引用替换为对HttpContextBase的引用。在代码中,使用HttpContextBase实例初始化HttpContextWrapper,这是web堆栈中的默认行为实现。

然而,在您的测试中,注入一个自定义HttpContextBase实现,其中您只实现测试所需的方法和行为。

如链接中所述:

HttpContextBase类是一个抽象类,它包含与HttpContext类相同的成员。HttpContextBase类使您能够创建类似于HttpContext类的派生类,但可以自定义并在ASP.NET管道之外工作。在执行单元测试时,通常使用派生类来实现具有自定义行为的成员,以满足所测试的场景。

票数 1
EN

Stack Overflow用户

发布于 2014-09-19 15:39:46

将控制器与HTTP上下文分离。这里可能有一些我不熟悉的内置功能,但是一种方法是简单地注入一个可模拟的对象。考虑一下这样的事情:

代码语言:javascript
复制
public interface IRequestInformation
{
    string UserHostAddress { get; }
}

public class RequestInformation : IRequestInformation
{
    public string UserHostAddress
    {
        get { return HttpContext.Current.Request.UserHostAddress; }
    }
}

现在,您已经抽象了接口后面对HttpContext的依赖关系。如果使用依赖项注入,则将该接口插入到控制器中。如果你不是,你可以假装:

代码语言:javascript
复制
// in your controller...
private IRequestInformation _request;
public IRequestInformation RequestInfo
{
    get
    {
        if (_request == null)
            _request = new RequestInformation();
        return _request;
    }
    set { _request = value; }
}

然后在控制器逻辑中使用它:

代码语言:javascript
复制
string ip = RequestInfo.UserHostAddress;

现在,在单元测试中,您可以为RequestInfo属性提供一个模拟/假/等等。要么手动创建一个,要么使用模拟库。如果手动创建一个,这就足够简单了:

代码语言:javascript
复制
public class RequestInformationFake : IRequestInformation
{
    public string UserHostAddress
    {
        get { return "some known value"; }
    }
}

然后,在安排测试时,只需将其提供给控制器:

代码语言:javascript
复制
var controller = new YourController();
controller.RequestInformation = new RequestInformationFake();
// run your test
票数 4
EN

Stack Overflow用户

发布于 2020-05-22 02:35:02

将下列方法添加到控制器中,或注入等效的方法。它使用神奇的字符串MS_HttpContext,因为这正是AspNetWebStack 实现所使用的完全相同的目的。

代码语言:javascript
复制
HttpContextBase HttpContextBase => HttpContext.Current != null
    ? new HttpContextWrapper(HttpContext.Current)
    : (HttpContextBase)Request.Properties["MS_HttpContext"]

将控制器中HttpContext.Current的所有其他用途替换为HttpContextBase

当单元测试:

代码语言:javascript
复制
var context = new Mock<HttpContextBase>();
...

controller.Request = new HttpRequestMessage();
controller.Request.Properties["MS_HttpContext"] = context.Object;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25937456

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档