如何伪造 HttpContext 进行单元测试?

发布于 2024-09-14 06:34:22 字数 285 浏览 4 评论 0原文

我需要伪造 HttpContext.Current.Application 表才能从单元测试中访问它。

我需要将我的数据存储在某个地方。我以为我可以只传递 NameValueCollectionBase 的实例,但我发现这个基本类型没有索引器,所以使用起来似乎太复杂了。

那么伪造 HttpContext 的这一部分怎么样?是否可以?我怎样才能做到呢? NUnit.Mocks 有帮助吗?

先感谢您...

I need to fake HttpContext.Current.Application table in order to access it from my unit tests.

I need to store my data somewhere. I thought that I can just pass instance of NameValueCollectionBase but as I discovered this base type has no indexer so it seems too complicated to use.

So what about faking this part of HttpContext? Is it possible? How can I make it? Will be NUnit.Mocks helpful?

Thank you in advance...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

坚持沉默 2024-09-21 06:34:22

如果您需要 namevaluecollection 基础的索引,请使用下面的代码,

public static IEnumerable<KeyValuePair<string, string>> ToPairs(this NameValueCollection collection)
{
    if(collection == null)
    {
        throw new ArgumentNullException("collection");
    }

    return collection.Cast<string>().Select(key => new KeyValuePair<string, string>(key, collection[key]));
}

如果只是为了存储数据并传递测试方法,请使用上面的代码。

If you need indexes for namevaluecollection base please use below code

public static IEnumerable<KeyValuePair<string, string>> ToPairs(this NameValueCollection collection)
{
    if(collection == null)
    {
        throw new ArgumentNullException("collection");
    }

    return collection.Cast<string>().Select(key => new KeyValuePair<string, string>(key, collection[key]));
}

For just to store data and passing around test methods please use above code.

对你再特殊 2024-09-21 06:34:22

在这种情况下,我生成一些从 System.Web.Abstractions 中的基类派生的存根。我经常在 MVC 应用程序中使用这种技术,因为 MVC / WebApi 控制器包含对 HttpContext (HttpContextBase) 的抽象,

这样我就可以在我的单元/集成测试中消除 HttpContext 需求,这是一个示例...

public class MockHttpApplicationState : HttpApplicationStateBase
{
    private IDictionary<string, object> _appState = new Dictionary<string, object>();

    public override void Add(string name, object value)
    {
        _appState.Add(name, value);
    }

    public override object Get(string name)
    {
        return _appState[name];
    }

    public override object this[string name]
    {
        get
        {
            return _appState[name];
        }

        set
        {
            _appState[name] = value;
        }
    }
}

public class MockHttpContext : HttpContextBase
{
    private IDictionary<string, object> _appKeys;

    public MockHttpContext()
    {

    }

    /// <summary>
    /// Accepts a dictionary of app keys to supply to the HttpApplicationState instance
    /// </summary>
    /// <param name="applicationState"></param>
    public MockHttpContext(IDictionary<string,object> applicationState)
    {
        _appKeys = applicationState;
    }

    public override Cache Cache
    {
        get
        {                
            return HttpRuntime.Cache;
        }
    }

    public override HttpApplicationStateBase Application
    {
        get
        {
            var mockAppState = new MockHttpApplicationState();

            foreach (string key in _appKeys.Keys)
            {
                mockAppState.Add(key, _appKeys[key]);
            }

            return mockAppState;
        }
    }

    public override HttpRequestBase Request
    {
        get
        {
            return new HttpRequestWrapper(new HttpRequest(null,"http://localhost",null));
        }
    }
}

然后我的测试可以建立 Controller 和 Http上下文:

private readonly OnlineShop.MVC.Controllers.HomeController _controller = 
        new MVC.Controllers.HomeController(null,new UnitOfWork());

    [OneTimeSetUp]
    public void Init()
    {
        var appKeys = new Dictionary<string, object>();

        appKeys.Add("localhost", 1);

        var httpContext = new MockHttpContext(appKeys);

        _controller.ControllerContext = new ControllerContext()
        {
            Controller = _controller,
            RequestContext = new RequestContext(httpContext, new RouteData())    
        };                        
    }

    [Test]
    public void Index_Returns_HomeView()
    {            
        var view = _controller.Index() as ViewResult;
        var viewModel = view.Model as MVC.ViewModels.Home;

        Assert.IsInstanceOf<OnlineShop.MVC.ViewModels.Home>(viewModel);
        Assert.IsTrue(viewModel.FeaturedProducts.Count > 0);
    }

我的控制器知道它的环境 HttpContextBase 实例提供缓存和应用程序状态:

  public ActionResult Index()
    {                        
        string cacheKey = string.Format("FeaturedProducts-{0}",WebsiteId);
        IList<Product> productList = this.HttpContext.Cache[cacheKey] as IList<Product>;


        //My app keeps a list of website contexts in the Application. This test returns 1 based on the unit / int tests or a real world db value when hosted on IIS etc..
        int websiteId = (int)HttpContext.Application[this.Request.Url.Host];

In this scenario I generate some stubs derived from the base classes in System.Web.Abstractions. I often use this technique for MVC applications as MVC / WebApi controllers contain an abstraction to HttpContext (HttpContextBase)

This way I can stub out HttpContext requirements in my unit / integration tests, here's a sample...

public class MockHttpApplicationState : HttpApplicationStateBase
{
    private IDictionary<string, object> _appState = new Dictionary<string, object>();

    public override void Add(string name, object value)
    {
        _appState.Add(name, value);
    }

    public override object Get(string name)
    {
        return _appState[name];
    }

    public override object this[string name]
    {
        get
        {
            return _appState[name];
        }

        set
        {
            _appState[name] = value;
        }
    }
}

public class MockHttpContext : HttpContextBase
{
    private IDictionary<string, object> _appKeys;

    public MockHttpContext()
    {

    }

    /// <summary>
    /// Accepts a dictionary of app keys to supply to the HttpApplicationState instance
    /// </summary>
    /// <param name="applicationState"></param>
    public MockHttpContext(IDictionary<string,object> applicationState)
    {
        _appKeys = applicationState;
    }

    public override Cache Cache
    {
        get
        {                
            return HttpRuntime.Cache;
        }
    }

    public override HttpApplicationStateBase Application
    {
        get
        {
            var mockAppState = new MockHttpApplicationState();

            foreach (string key in _appKeys.Keys)
            {
                mockAppState.Add(key, _appKeys[key]);
            }

            return mockAppState;
        }
    }

    public override HttpRequestBase Request
    {
        get
        {
            return new HttpRequestWrapper(new HttpRequest(null,"http://localhost",null));
        }
    }
}

Then my test can establish Controller and Http Context:

private readonly OnlineShop.MVC.Controllers.HomeController _controller = 
        new MVC.Controllers.HomeController(null,new UnitOfWork());

    [OneTimeSetUp]
    public void Init()
    {
        var appKeys = new Dictionary<string, object>();

        appKeys.Add("localhost", 1);

        var httpContext = new MockHttpContext(appKeys);

        _controller.ControllerContext = new ControllerContext()
        {
            Controller = _controller,
            RequestContext = new RequestContext(httpContext, new RouteData())    
        };                        
    }

    [Test]
    public void Index_Returns_HomeView()
    {            
        var view = _controller.Index() as ViewResult;
        var viewModel = view.Model as MVC.ViewModels.Home;

        Assert.IsInstanceOf<OnlineShop.MVC.ViewModels.Home>(viewModel);
        Assert.IsTrue(viewModel.FeaturedProducts.Count > 0);
    }

And my controller is aware of it's ambient HttpContextBase instance supplying Cache and Application state:

  public ActionResult Index()
    {                        
        string cacheKey = string.Format("FeaturedProducts-{0}",WebsiteId);
        IList<Product> productList = this.HttpContext.Cache[cacheKey] as IList<Product>;


        //My app keeps a list of website contexts in the Application. This test returns 1 based on the unit / int tests or a real world db value when hosted on IIS etc..
        int websiteId = (int)HttpContext.Application[this.Request.Url.Host];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文