在我正在进行的一个项目中,我终于可以为项目的一部分编写 SpecFlow 功能测试了。
但是,有一个小问题——我们的应用程序中有一个授权过滤器,我需要为一些测试调用它。
授权过滤器看起来有点像这样(这里有很多编辑)
public class Authorization : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if(filterContext == null
|| filterContext.Controller == null
|| filterContext.Controller.ControllerContext == null)
throw new ArgumentException("Incomplete filter context.");
if(! filterContext.Controller.ControllerContext.IsChildAction)
{
if(filterContext.RequestContext == null
|| filterContext.RequestContext.HttpContext == null
|| filterContext.RequestContext.HttpContext.Request == null
|| filterContext.RequestContext.HttpContext.Request.Url == null)
throw new ArgumentException("Incomplete request in filter context.");
// SNIP: Authorization checks and activities.
// This one line is a bit tricky to mock...
HttpRequestBase request = filterContext.HttpContext.Request;
// SNIP: Other activities that come after
}
}
// SNIP: Other supporting methods that don't pertain to the problem domain.
}
...在我的功能测试中,我试图在一个特殊的 Given 步骤中调用它:
[Given(@"I am logged in as (.*)")]
public void GivenIAmLoggedInAsX(string userId)
{
_controller = new SpecificController();
_controller.ControllerContext = new ControllerContext(new HttpContextMock(), new RouteData(), _controller);
Authorization authorize = new Authorization();
AuthorizeContext authContext = new AuthorizationContext(_controller.ControllerContext);
authorize.OnAuthorization(authContext);
// SNIP: Other activities that don't pertain to the question.
}
...这不起作用,通过NotImplementedExceptions
在我正在构建的测试用例上生成许多。
问了我的团队后,有人提到了ControllerActionInvoker
MVC 中的类。可悲的是,MS 文档在细节上有点粗制滥造,例如如何最好地使用它。
此外,StackOverflow在我试图弄清楚如何使用 ControllerActionInvoker 时也失败了。 WayBack Machine也没有太大帮助。
我尝试了几种不同的方法作为临时措施,但没有产生任何结果,而且很沮丧。
问题:我绝对需要在我正在使用的功能测试中调用此过滤器,而直接方法不起作用。为功能测试调用过滤器的最佳方法是什么?
旁注:整个 MVC 过滤系统对我来说是未开发的领域,所以有很多我不知道的。在你的回答中,假设我几乎一无所知,因为这可能是准确的,即使我已经对如何做到这一点进行了研究。
替代实施#1
我发现我的原始示例使用了一个过时的构造函数;推荐使用 2-arg 构造函数。所以,我用它没有什么好的效果。这是它的样子(仍然是直接的方法:)
[Given(@"I am logged in as (.*)")]
public void GivenIAmLoggedInAsX(string userId)
{
_controller = new RequestFormController();
_controller.ControllerContext = new ControllerContext(new HttpContextMock(), new RouteData(), _controller);
Authorization authorize = new Authorization();
MethodInfo method = typeof (MyController).GetMethod("MyAction");
ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(typeof(MyController));
ActionDescriptor actionDescriptor = new ReflectedActionDescriptor(method, "MyAction", controllerDescriptor);
AuthorizationContext authContext = new AuthorizationContext(_controller.ControllerContext, actionDescriptor);
authorization.OnAuthorization(authContext);
// SNIP: Unrelated code.
}