English 中文(简体)
缩略语
原标题:MVC3 HttpContext unit testing / mocking options

因此,这确实适用于诸如HttpContext、ConigurationManager等几个不同类别。 处理这一问题有几种不同的方式,我总是利用总结班处理这一难题,但我希望看到,最常见的社区做法是......。

  1. Wrapper classes - e.g. I would have an HttpContextService which I pass in via constructor that exposes all the same functionality via flat method calls.
  2. Wrapper classes (part 2) - e.g. I would have SPECIFIC service classes, like MembershipService, which LEVERAGES HttpContext behind the scenes. Functions the same as 1, but the naming scheme / usage pattern is a little different as you are exposing specific functions through specific services instead of one monolithic wrapper. The downside is that the number of service classes that need to be injected goes up, but you get some modularity for when you don t need all the features of the monolithic wrapper.
  3. ActionFilters and parameters - Use an ActionFilter to automatically pass in certain values needed on a per function basis. MVC only, and limits you to the controller methods, whereas 1 and 2 could be used generically throughout the project, or even in conjunction with this option.
  4. Directly mocking HttpContextBase and setting ControllerContext - There are several mocking framework extension methods out there to help with this, but essentially requires you to directly set things as needed. Doesn t require abstractions, which is nice, and can be reused across non-controller tests as well. Still leaves open the question for ConfigurationManager and other static method calls though, so you could end up with injecting that ANYWAY, but leaving HttpContext to be accessed in this other way.

Right now I am kind of doing number 1, so I have an HttpContextService and a ConfigurationManagerService, etc. which I then inject, though I m leaning toward 2 in the future. 3 seems to be a little too messy for my tastes, but I can see the appeal for controller methods, and the need for a completely separate solution for other areas of code that also use these static classes makes that one kind of poor for me... 4 is still interesting to me as it seems the most "natural" in terms of basic functionality and leverages the built-in methodologies of MVC.

因此,这里的主要最佳做法是什么? 人们在野中看到和使用什么?

问题回答

There are already "wrapper" classes for HttpContext, HttpRequest, HttpResponse, etc. The MVC framework uses these and you can supply mocks of them to the Controller via the controller context. You don t need to mock the controller context as you can simply create one with the appropriate values. The only thing I ve found difficult to mock are the helpers, UrlHelper and HtmlHelper. Those have some relatively deep dependencies. You can fake them in a somewhat reasonable way, UrlHelper shown below.

 var httpContext = MockRepository.GenerateMock<HttpContextBase>();
 var routeData = new RoutedData();

 var controller = new HomeController();
 controller.ControllerContext = new ControllerContext( httpContext, routeData, controller );
 controller.Url = UrlHelperFactory.CreateUrlHelper( httpContext, routeDate );

地点

 public static class UrlHelperFactory
 {
    public static UrlHelper CreateUrlHelper( HttpContextBase httpContext, RouteData routeData )
    {
        return CreateUrlHelper( httpContext, routeData, "/" );
    }

    public static UrlHelper CreateUrlHelper( HttpContextBase httpContext, RouteData routeData, string url )
    {
        string urlString = string.Format( "http://localhost/{0}/{1}/{2}", routeData.Values["controller"], routeData.Values["action"], routeData.Values["id"] ).TrimEnd(  /  );

        var uri = new Uri( urlString );

        if (httpContext.Request == null)
        {
            httpContext.Stub( c => c.Request ).Return( MockRepository.GenerateStub<HttpRequestBase>() ).Repeat.Any();
        }

        httpContext.Request.Stub( r => r.Url ).Return( uri ).Repeat.Any();
        httpContext.Request.Stub( r => r.ApplicationPath ).Return( "/" ).Repeat.Any();

        if (httpContext.Response == null)
        {
            httpContext.Stub( c => c.Response ).Return( MockRepository.GenerateStub<HttpResponseBase>() ).Repeat.Any();
        }
        if (url != "/")
        {
            url = url.TrimEnd(  /  );
        }

        httpContext.Response.Stub( r => r.ApplyAppPathModifier( Arg<string>.Is.Anything ) ).Return( url ).Repeat.Any();

        return new UrlHelper( CreateRequestContext( httpContext, routeData ), GetRoutes() );
    }

    public static RequestContext CreateRequestContext( HttpContextBase httpContext, RouteData routeData )
    {
        return new RequestContext( httpContext, routeData );
    }

    // repeat your route definitions here!!!
    public static RouteCollection GetRoutes()
    {
        RouteCollection routes = new RouteCollection();
        routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" );


        routes.MapRoute(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "home", action = "index", id = "" }  // Parameter defaults
        );

        return routes;
    }
}




相关问题
run unit tests and coverage in certain python structure

I have some funny noob problem. I try to run unit tests from commandline: H:PROpyEstimator>python src estpython est_power_estimator.py Traceback (most recent call last): File "src est...

How to unit-test an enterprise symfony project?

I´m working on a huge project at my work. We have about 200 database tables, accordingly a huge number of Models, Actions and so on. How should I begin to write tests for this? My biggest problem ...

Code Coverage Tools & Visual Studio 2008 Pro

Just wondering what people are using for code coverage tools when using MS Visual Studio 2008 Pro. We are using the built-in MS test project and unit testing tool (the one that come pre-installed ...

Unit testing. File structure

I have a C++ legacy codebase with 10-15 applications, all sharing several components. While setting up unittests for both shared components and for applications themselves, I was wondering if there ...

Unit Testing .NET 3.5 projects using MStest in VS2010

There s a bug/feature in Visual Studio 2010 where you can t create a unit test project with the 2.0 CLR. https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=483891&wa=...

Unit Test for Exceptions Message

Is there a simple (Attribute-driven) way to have the following test fail on the message of the exception. [TestMethod()] [ExpectedException(typeof(ArgumentException))] public void ExceptionTestTest() ...

热门标签