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

走远了吗. 提交于 2020-01-03 17:10:54

问题


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 ?


回答1:


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();
    }
}


来源:https://stackoverflow.com/questions/18534953/nsubstitute-mocking-the-request-response-object-inside-a-mvc-web-api-controlle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!