NSubstitute:在MVC / Web Api控制器中模拟请求,响应对象?

时间:2013-08-30 14:07:28

标签: asp.net-mvc asp.net-web-api nsubstitute

我试图找到如何在MVC / Web Api中模拟控制器内可用的Request和Response对象。

这是可能的,我没有注入Request和Response对象,这些是可用的,因为控制器继承自ApiController或Controller。

有没有人有一些很好的例子可以通过nsubstitute访问这些?

还有像上下文这样的其他对象呢?

1 个答案:

答案 0 :(得分:5)

你不必嘲笑他们。

由于它们具有读/写属性,您所要做的就是创建它们。我在book中解释了一下,我们有一个允许你这样做的课程:

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

我在这里分享代码所以可以使用它:

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