代码之家  ›  专栏  ›  技术社区  ›  lancscoder

asp.net mvc如何正确测试控制器

  •  5
  • lancscoder  · 技术社区  · 14 年前

    我测试控制器有困难。用于测试的原始控制器如下所示:

    SomethingController CreateSomethingController()
    {
        var somethingData = FakeSomethingData.CreateFakeData();
        var fakeRepository = FakeRepository.Create();
    
        var controller = new SomethingController(fakeRepository);
    
        return controller;
    }
    

    在我拿到证书之前,这在大多数测试中都很有效 Request.IsAjaxRequest() 代码的一部分。所以我不得不模拟HttpContext和HttpRequestBase。所以我的代码变成了:

    public class FakeHttpContext : HttpContextBase
    {
        bool _isAjaxRequest;
    
        public FakeHttpContext( bool isAjaxRequest = false )
        {
            _isAjaxRequest = isAjaxRequest;
        }
    
        public override HttpRequestBase Request
        {
            get
            {
                string ajaxRequestHeader = "";
    
                if ( _isAjaxRequest )
                    ajaxRequestHeader = "XMLHttpRequest";
    
                var request = new Mock<HttpRequestBase>();
                request.SetupGet( x => x.Headers ).Returns( new WebHeaderCollection 
                {
                    {"X-Requested-With", ajaxRequestHeader} 
                } );
    
                request.SetupGet( x => x["X-Requested-With"] ).Returns( ajaxRequestHeader );
    
                return request.Object;
            }
        }
    
        private IPrincipal _user;
    
        public override IPrincipal User
        {
            get
            {
                if ( _user == null )
                {
                    _user = new FakePrincipal();
                }
                return _user;
            }
            set
            {
                _user = value;
            }
        }
    }
    
    
    SomethingController CreateSomethingController()
    {
        var somethingData = FakeSomethingData.CreateFakeData();
        var fakeRepository = FakeRepository.Create();
    
        var controller = new SomethingController(fakeRepository);
    
        ControllerContext controllerContext = new ControllerContext( new FakeHttpContext( isAjaxRequest ), new RouteData(), controller );
         controller.ControllerContext = controllerContext;
    
        return controller;
    }
    

    Url.Route Url 为空。所以看起来我需要开始模拟我的控制器的路由。

    我似乎花了更多的时间在google上搜索如何伪造/模拟对象,然后调试以确保我的伪造是正确的,而不是实际编写测试代码。有没有更简单的方法来测试控制器?我已经看过了MvcContrib的TestControllerBuilder,它有助于解决一些问题,但似乎并不是万能的。还有什么可以做的工作,让我集中精力写测试,而不是写模拟?

    谢谢

    4 回复  |  直到 14 年前
        1
  •  1
  •   anthares    14 年前

    您可以使用一些提供这些对象的现成库。例如 RhinoMock , NMock Moq -它足够好而且免费。在Moq中我最喜欢的是linq表达式。

        2
  •  1
  •   BritishDeveloper    14 年前

    大多数模拟引擎会为你做这一切。我用 RhinoMocks 但是还有很多。阿尔索 Moles 是非常新和有趣的模拟引擎(这通常与Pex,这是更多的弹药在您的单元测试兵工厂)

        3
  •  1
  •   Community Egal    7 年前

    MvcContrib+RhinoMocks。查看MvcContrib.TestHelper库中的TestControllerBuilder。以下是官方报道: http://mvccontrib.codeplex.com/wikipage?title=TestHelper#Examples .

    ASP.NET MVC: Mock controller.Url.Action

    下面是如何使用TestControllerBuilder的简短说明: http://codebetter.com/blogs/kyle.baley/archive/2008/03/19/testcontrollerbuilder-in-mvccontrib.aspx

        4
  •  1
  •   queen3    14 年前

    您可以将IAjaxRequest传递给构造函数,而不是模拟内容。或者使其成为基本构造函数类属性(并使用属性注入)。或者您可以让您的构造函数实现IAjaxRequest,然后在将设置IAjaxRequest的基本构造函数类上应用全局操作筛选器。

    另一种方法是在需要特定信息的方法上直接使用模型绑定器。看到了吗 this post 例如。您可以创建一个binder,它将向您提供isajax请求,然后您只需执行接受此参数的操作。工作得很好,因为信息是准确地提供给需要它的方法,而不是整个控制器。