Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSubstitute: Mocking the request, response object inside a MVC/Web Api Controller?

I am trying to find how to mock both the Request and Response objects that are available inside a controller from MVC / Web Api.

Is this possible, I am not injecting the Request and Response objects, these are available because the controllers inherit from ApiController or Controller.

Does anyone have some good examples for getting access to these through nsubstitute ?

Also what about the other objects like context ?

like image 203
Martin Avatar asked Aug 30 '13 14:08

Martin


1 Answers

You do not have to mock them.

Since they have read/write properties, all you have to do is to create them. I explain it a bit more in our book and we have a class that allows you to do this:

var orderController = ControllerContextSetup
   .Of(() => new OrderController(mockOrderService.Object))
   .WithDefaultConfig()
   .WithDefaultRoute()
   .Requesting(url)
   .WithRouteData(new {controller="Order"})
   .Build<OrderController>();

I am sharing the code here so it can be used:

public class ControllerContextSetup
{

    private const string DefaultApiName = "DefaultApi";
    private readonly ApiController _controller;
    private HttpRouteData _httpRouteData;

    private ControllerContextSetup(ApiController controller)
    {
        _controller = controller;
        _controller.Request = new HttpRequestMessage();
    }

    public static ControllerContextSetup Of<T>(Func<T> factory)
        where T : ApiController
    {
        return new ControllerContextSetup(factory());
    }

    public static ControllerContextSetup Of<T>()
        where T : ApiController, new()
    {
        return new ControllerContextSetup(new T());
    }

    public ControllerContextSetup WithDefaultConfig()
    {
        _controller.Configuration = new HttpConfiguration();
        _controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = _controller.Configuration;
        return this;
    }

    public ControllerContextSetup WithConfig(HttpConfiguration configuration)
    {
        _controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = configuration;
        _controller.Configuration = configuration;
        return this;
    }

    public ControllerContextSetup Requesting(string uriString)
    {
        Uri uri = null;
        bool success = Uri.TryCreate(uriString, UriKind.Relative, out uri);
        if (success)
            return Requesting(uri);

        success = Uri.TryCreate(uriString, UriKind.Absolute, out uri);
        if(success)
            return Requesting(uri);

        return Requesting(new Uri(uriString));

    }

    public ControllerContextSetup Requesting(Uri uri)
    {
        _controller.Request.RequestUri = uri;
        return this;
    }

    public ControllerContextSetup WithDefaultRoute()
    {
        _controller.Configuration.Routes.MapHttpRoute(
            name: DefaultApiName,
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
            );
        return this;
    } 

    public ControllerContextSetup WithRoute(string name, string routeTemplate)
    {
        _controller.Configuration.Routes.MapHttpRoute(name, routeTemplate);
        return this;
    }

    public ControllerContextSetup WithRoute(string name, string routeTemplate, object defaults)
    {
        _controller.Configuration.Routes.MapHttpRoute(name, routeTemplate, defaults);
        return this;
    }

    public ControllerContextSetup WithRoute(string name, string routeTemplate, object defaults, object constraints)
    {
        _controller.Configuration.Routes.MapHttpRoute(name, routeTemplate, defaults, constraints);
        return this;
    }

    public ControllerContextSetup WithRoute(string name, IHttpRoute route)
    {
        _controller.Configuration.Routes.Add(name, route);
        return this;
    }

    /// <summary>
    /// Uses default route
    /// </summary>
    /// <param name="routeValues"></param>
    /// <returns></returns>
    public ControllerContextSetup WithRouteData(object routeValues)
    {
        return WithRouteData(new HttpRouteValueDictionary(routeValues));
    }

    /// <summary>
    /// Uses default route
    /// </summary>
    /// <param name="routeValues"></param>
    /// <returns></returns>
    public ControllerContextSetup WithRouteData(HttpRouteValueDictionary routeValues)
    {
        var route = _controller.Configuration.Routes[DefaultApiName];
        _httpRouteData = new HttpRouteData(route, routeValues); 
        _controller.Request.Properties[HttpPropertyKeys.HttpRouteDataKey] = _httpRouteData;
        return this;
    }

    public ControllerContextSetup WithMethod(HttpMethod method)
    {
        _controller.Request.Method = method;
        return this;
    } 

    public ApiController Build()
    {
        _controller.ControllerContext =
            new HttpControllerContext(_controller.Configuration, 
                _httpRouteData ?? new HttpRouteData(_controller.Configuration.Routes.FirstOrDefault()) , 
                _controller.Request);
        return _controller;
    }


    public T Build<T>()
        where T : ApiController
    {
        return (T) Build();
    }
}
like image 172
Aliostad Avatar answered Oct 29 '22 17:10

Aliostad