5

我试图找到如何从 MVC / Web Api 模拟控制器内部可用的请求和响应对象。

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

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

还有其他对象,比如 context 呢?

4

1 回答 1

5

你不必嘲笑他们。

由于它们具有读/写属性,您所要做的就是创建它们。我在我们的书中对其进行了更多解释,我们有一个类可以让你这样做:

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();
    }
}
于 2013-08-30T14:38:31.833 回答