【问题标题】:ControllerContext.HttpContext initialization for unit testsControllerContext.HttpContext 初始化单元测试
【发布时间】:2013-04-08 14:55:50
【问题描述】:

在为Controller编写单元测试的过程中,我需要设置或初始化-

ControllerContext.HttpContext.Request.QueryString

最简单的设置方法是什么,这样我才能真正通过 - ControllerContext.HttpContext.Request.QueryString - 并测试控制器?

【问题讨论】:

    标签: c# asp.net-mvc-3 unit-testing controller


    【解决方案1】:

    您可以使用模拟框架来模拟控制器正在使用的 HttpContext。

    例如NSubstitute:

    // arrange
    var contextMock = Substitute.For<HttpContextBase>();
    var requestMock = Substitute.For<HttpRequestBase>();
    var queryString = new NameValueCollection();
    queryString["foo"] = "bar";
    requestMock.QueryString.Returns(queryString);
    contextMock.Request.Returns(requestMock);
    var sut = new SomeController();
    sut.ControllerContext = new ControllerContext(contextMock, new RouteData(), sut);
    
    // act
    var actual = sut.SomeAction(); 
    
    // assert
    ...
    

    当然,您可以使用您喜欢的任何其他模拟框架,例如 Moq 或 Rhino Mocks 来模拟 HttpContext。

    顺便说一句,如果您使用视图模型(在正确设计的 ASP.NET MVC 应用程序中应该始终这样做),您甚至不会关心 Request.QueryString,因为您的控制器操作现在将视图模型作为参数:

    public ActionResult SomeAction(MyViewModel model)
    {
        ...
    }
    

    默认模型绑定器会考虑到请求参数与模型的绑定。您应该避免在控制器操作中编写管道代码,从查询字符串和内容中提取一些数据。

    看看你的单元测试现在变得多么可读:

    var model = new MyViewModel();
    model.Foo = "bar";
    var sut = new SomeController();
    
    // act
    var actual = sut.SomeAction(model); 
    
    // assert
    ...
    

    看到了吗?您不再需要关心管道代码。

    【讨论】:

    • 只是想知道以这种方式编写单元测试是否是一种好习惯,以了解数据将如何从请求者传入。因此,我的控制器由带有 QueryString 的 GET 启动,因此我使用测试字符串查询,并且希望模型绑定器为我创建对象,而无需模拟控制器上的具体模型。我知道你可能会说什么......我们应该相信模型绑定器,并且只为功能部分编写单元测试,而不考虑入口点......但是通过省略模型绑定器感觉就像在作弊? :(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    • 2016-07-13
    • 2011-03-09
    • 2017-09-10
    • 1970-01-01
    相关资源
    最近更新 更多