集成测试中的MVC策略覆盖

时间:2019-05-30 13:30:39

标签: c# asp.net testing xunit

我正在为MVC应用添加正在使用的集成测试。我们的许多端点都对其应用了策略,例如

namespace WorkProject
{
  [Route("A/Route")]
  public class WorkController : Controller
  {
    [HttpPost("DoStuff")]
    [Authorize(Policy = "CanDoStuff")]
    public IActionResult DoStuff(){/* */}
  }
}

对于我们的集成测试,我像ASP .NET Core documentation中所建议的那样覆盖了WebApplicationFactory。我的目标是制作一个允许所有各方通过授权策略的类,从而使身份验证步骤超载并绕过策略。

namespace WorkApp.Tests
{
    public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup: class
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            base.ConfigureWebHost(builder);
            builder.ConfigureServices(services =>
            {
                services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = "Test Scheme"; // has to match scheme in TestAuthenticationExtensions
                    options.DefaultChallengeScheme = "Test Scheme";
                }).AddTestAuth(o => { });


                services.AddAuthorization(options =>
                {
                    options.AddPolicy("CanDoStuff", policy =>
                        policy.Requirements.Add(new CanDoStuffRequirement()));
                });

             // I've also tried the line below, but neither worked
             // I figured that maybe the services in Startup were added before these
             // and that a replacement was necessary
             // services.AddTransient<IAuthorizationHandler, CanDoStuffActionHandler>();
             services.Replace(ServiceDescriptor.Transient<IAuthorizationHandler, CanDoStuffActionHandler>());
            });
        }
    }

    internal class CanDoStuffActionHandler : AuthorizationHandler<CanDoStuffActionRequirement>
    {
        public CanDoStuffActionHandler()
        {
        }

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CanDoStuffActionRequirement requirement)
        {
            context.Succeed(requirement);

            return Task.CompletedTask;
        }
    }

    internal class CanDoStuffRequirement : IAuthorizationRequirement
    {
    }
}

我对服务所做的第一件事是按照建议的here覆盖身份验证(没有一点关于覆盖Startup的问题,因为这似乎不适用于我)。我倾向于认为此身份验证覆盖有效。运行测试时,我从xUnit测试框架中收到HTTP 403。如果我从PostMan测试了路由,则会收到HTTP401。我还创建了一个类,该类位于自定义Web应用程序工厂中,该工厂允许对CanDoStuff授权处理程序的所有请求。我以为这将允许通过授权策略进行集成测试,但是如上所述,我收到了HTTP403。我知道如果应用程序不知道某些文件在哪里,则会返回403。但是,这是一条严格用于接收和处理数据的后继路由,并且该路由不会尝试返回任何视图,因此,此403很可能与由于某些原因未被覆盖的授权策略有关。

我显然做错了什么。当我在调试模式下运行测试并在HandleRequirementsAsync函数中设置断点时,应用程序永不中断。我应该尝试以其他方式覆盖授权策略吗?

1 个答案:

答案 0 :(得分:1)

这就是我所做的。

  1. 用我自己的WebApplicationFactory覆盖。注意,我仍然将应用程序的启动添加为模板参数
  2. 创建我在其中添加的overrides the ConfigureAuthServices函数的启动函数。
  3. height: xxxpx;函数中告诉构建器以使用我的自定义启动类。
  4. 通过#cytoscape-container覆盖.cytoscape-parent函数中的身份验证步骤。
  5. 向我要在ConfigureWebHost函数中ConfigureWebHost的结尾处尝试访问其端点的控制器添加程序集引用。
  6. 为允许所有请求成功的策略写自己的builder.ConfigureServices

我希望我在解释自己所做的工作方面做得不错。如果不是这样,希望下面的示例代码足够容易理解。

YourController.cs

builder.ConfigureServices

Test.cs

ConfigureWebHost

CustomWebApplicationFactory.cs

IAuthorizationHandler

TestStartup.cs

namespace YourApplication
{
  [Route("A/Route")]
  public class WorkController : Controller
  {
    [HttpPost("DoStuff")]
    [Authorize(Policy = "CanDoStuff")]
    public IActionResult DoStuff(){/* */}
  }
}