集成测试中的 MVC 策略覆盖

2024-03-17

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

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

对于我们的集成测试,我已经覆盖了WebApplicationFactory就像建议的那样ASP .NET Core 文档 https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2。我的目标是重载身份验证步骤,并通过创建一个允许所有各方通过授权策略的类来绕过策略。

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 https://medium.com/@jackwild/bypassing-asp-net-core-2-0-authorize-tags-in-integration-tests-7bda8fcb0eca(没有关于覆盖的位Startup因为这似乎对我不起作用)。我倾向于相信这种身份验证覆盖是有效的。当我运行测试时,我从 xUnit 测试框架内收到 HTTP 403。如果我点击从 PostMan 测试的路由,我会收到 HTTP 401。我还创建了一个位于自定义 Web 应用程序工厂中的类,该类允许对CanDoStuff授权处理程序。我认为这将允许通过授权策略进行集成测试,但是,如上所述,我收到 HTTP 403。我知道如果应用程序不知道某些文件在哪里,则会返回 403。然而,这是严格用于接收和处理数据的后路由,并且该路由不会尝试返回任何视图,因此该 403 很可能与授权策略相关,由于某种原因,该策略未被覆盖。

我显然做错了什么。当我在调试模式下运行测试并在HandleRequirementsAsync功能,应用程序永远不会中断。我应该尝试以不同的方式覆盖授权策略吗?


这就是我所做的。

  1. 覆盖WebApplicationFactory https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2和我自己的。注意,我仍然添加了应用程序的启动作为模板参数
  2. 创建我的启动函数覆盖ConfigureAuthServices https://medium.com/@jackwild/bypassing-asp-net-core-2-0-authorize-tags-in-integration-tests-7bda8fcb0eca我添加的功能。
  3. 告诉建筑商ConfigureWebHost函数来使用我的自定义启动类。
  4. 覆盖中的身份验证步骤ConfigureWebHost功能通过builder.ConfigureServices.
  5. 添加对控制器的程序集引用,我试图在末尾命中该控制器的端点builder.ConfigureServices in the ConfigureWebHost功能。
  6. 写我自己的IAuthorizationHandler允许所有请求成功的策略。

我希望我已经很好地解释了我所做的事情。如果没有,希望下面的示例代码足够容易理解。

YourController.cs

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

Test.cs

namespace YourApplication.Tests
{
    public class Tests
        : IClassFixture<CustomWebApplicationFactory<YourApplication.Startup>>
    {
        private readonly CustomWebApplicationFactory<YourApplication.Startup> _factory;

        public Tests(CustomWebApplicationFactory<YourApplication.Startup> factory)
        {
            _factory = factory;
        }

        [Fact]
        public async Task SomeTest()
        {
            var client = _factory.CreateClient();
            var response = await client.PostAsync("/YourEndpoint");
            response.EnsureSuccessStatusCode();

            Assert.Equal(/* whatever your condition is */);
        }
    }
}

CustomWebApplicationFactory.cs

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

             services.AddMvc().AddApplicationPart(typeof(YourApplication.Controllers.YourController).Assembly);
             services.AddTransient<IAuthorizationHandler, CanDoStuffActionHandler>();
            });
            builder.UseStartup<TestStartup>();
        }
    }

    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
    {
    }
}

测试启动.cs

namespace YourApplication.Tests
{
    public class TestStartup : YourApplication.Startup
    {
        public TestStartup(IConfiguration configuration) : base(configuration)
        {

        }

        protected override void ConfigureAuthServices(IServiceCollection services)
        {
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

集成测试中的 MVC 策略覆盖 的相关文章

  • 何时使用 =default 使析构函数默认?

    尽管对构造函数使用 default 对我来说很清楚 即强制编译器在其他构造函数存在时创建默认构造函数 但我仍然无法理解这两种类型的析构函数之间的区别 那些使用 default 的 那些没有显式定义并由编译器自动生成的 我唯一想到的是 gro
  • 更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3

    我正在尝试更改 Qt OpenGL 示例以使用更现代的 opengl 版本 330 似乎合适 所以我做了 在 main cpp 上设置版本和配置文件 设置着色器版本 更改着色器以使用统一 它现在构建没有任何错误 但我只看到一个空白窗口 我错
  • VS 程序在调试模式下崩溃,但在发布模式下不崩溃?

    我正在 VS 2012 中运行以下程序来尝试 Thrust 函数查找 include cuda runtime h include device launch parameters h include
  • 类特定的新删除运算符是否必须声明为静态

    标准中是否要求类特定的 new new delete 和 delete 是静态的 我可以让它们成为非静态成员运算符吗 为什么需要它们是静态的 它们被隐式声明为静态 即使您没有键入 static
  • 指向特征矩阵的指针数组

    我在代码中使用 Eigen 的 MatrixXd 矩阵 在某个时刻我需要一个 3D 矩阵 由于 Eigen 没有三维矩阵类型 因为它仅针对线性代数进行了优化 因此我创建了一个 MatrixXd 类型的指针数组 Eigen MatrixXd
  • 为什么这个没有特殊字符的正则表达式会匹配更长的字符串?

    我正在使用此方法来尝试查找匹配项 例如 Regex Match A2 TS OIL TS OIL RegexOptions IgnoreCase Success 我得到了真实的结果 我很困惑 我认为这应该返回 false 因为模式中没有特殊
  • 动态生成的控件 ID 返回为 NULL

    我可以在 Page PreInit 函数中创建动态控件 如何检索控件及其 ID 我的 C 代码用于创建动态控件之一 var btn new WebForms Button btn Text btn ID Addmore btn Click
  • ASP.NET 中获取当前域的最佳方法是什么?

    我想知道在 ASP NET 中获取当前域的最佳方法是什么 例如 http www domainname com subdir http www domainname com subdir 应该产生http www domainname co
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • 在 ASP.NET 3.5 中使用 ASMX 文件的 WS-Security

    基本上 我需要设置 ASMX 文件 以便当我在浏览器中将其拉出以显示 WebMethod 规范时 Soap 标头符合以下格式
  • C++ php 和静态库

    我创建了一个library a 其中包含 cpp 和 h 文件 其中包含很多类 嵌套类和方法 我想在 php 示例中包含这个静态库并尝试使用它 我想提一下 我是 php 新手 我已经在 test cpp 文件中测试了我的 libray a
  • 检查 RoutedEvent 是否有任何处理程序

    我有一个自定义 Button 类 当单击它时 打开特定窗口 它总是执行相同的操作 我添加了一个可以在按钮的 XAML 中分配的 Click 事件 就像常规按钮一样 当它被单击时 我想执行 Click 事件处理程序 如果已分配 否则我想执行默
  • 将二进制数据从 C# 上传到 PHP

    我想将文件从 Windows C 应用程序上传到运行 PHP 的 Web 服务器 我知道 WebClient UploadFile 方法 但我希望能够分块上传文件 以便我可以监控进度并能够暂停 恢复 因此 我正在读取文件的一部分并使用 We
  • 给出 5 个参数,但在终端中只得到 3 个参数

    我想将一个文件传递给一个c 程序 如果我在 IDE 中执行此操作 test string string lt test txt return argc 5 但在终端上我刚刚得到argc 3 看来 这是因为 什么是 lt 意思是 我正在使用
  • 运行选定的代码生成器时出错:“未将对象引用设置到对象的实例。”错误?

    我已经尝试了所有解决方案 例如修复 VS 2013 但没有用 当您通过右键单击控制器文件夹来创建控制器并添加控制器时 然后右键单击新创建的控制器的操作并选择添加视图 当我尝试创建视图时 就会发生这种情况 它不是一个新项目 而是一个现有项目
  • ASP.NET MailMessage.BodyEncoding 和 MailMessage.SubjectEncoding 默认值

    很简单的问题 但我在 MSDN 上找不到答案 查找 ASP NET 将用于的默认值 MailMessage BodyEncoding and MailMessage SubjectEncoding 如果你不在代码中设置它们 Thanks F
  • IEnumerable.Except 不起作用,那么我该怎么办?

    我有一个 linq to sql 数据库 非常简单 我们有 3 个表 项目和用户 有一个名为 User Projects 的连接表将它们连接在一起 我已经有了一个获得的工作方法IEnumberable
  • 新任务中使用的依赖注入服务

    我在需要时使用依赖项注入来访问我的服务 但我现在想要创建一个并发任务 但这会由于依赖项注入对象及其生命周期而导致问题 我读过这篇文章 标题 防止多线程 Link http mehdi me ambient dbcontext in ef6
  • 了解使用 Windows 本机 WPF 客户端进行 ADFS 登录

    我已经阅读了大量有关 ADFS 与 NodeJS Angular 或其他前端 Web 框架集成以及一般流程如何工作的文献 并通过 Auth0 Angular 起始代码构建了概念证明 但我不明白如何这可以与本机 WPF Windows 应用程
  • C++ Streambuf 方法可以抛出异常吗?

    我正在尝试找到一种方法来获取读取或写入流的字符数 即使存在错误并且读 写结束时间较短 该方法也是可靠的 我正在做这样的事情 return stream rdbuf gt sputn buffer buffer size 但如果streamb

随机推荐

  • 接口中的协变返回类型未通过 Javac 编译

    我有以下结构 public interface BarReturn public interface FooReturn public interface FooBarReturn extends FooReturn BarReturn p
  • 无法在 firebase 云函数中创建自定义令牌,因为服务帐户没有必要的权限

    打电话时admin auth createCustomToken 我收到以下错误 需要 iam serviceAccounts signBlob 权限才能对服务帐户项目 serviceAccounts k 执行此操作 电子邮件受保护 cdn
  • 使用 #!/usr/bin/php 时自定义 php.ini

    我有一个脚本 我试图在其中加载自定义php ini文件 该脚本通过以下方式在 nix 系统上运行 usr bin php qc path to php ini标头 然而 当这样做时 PHP 报告加载的php ini文件不存在 即没有加载 如
  • 在 ondrag 事件期间,pageX 和 pageY 在 Firefox 中始终设置为 0

    我正在实现一个可视化编辑器 允许用户将图像拖动到页面上 并将其他图像拖动到这些先前拖动的图像中 类似于 添加另一个图像 我基本上只需要拖动过程中的鼠标坐标 元素 hiliting 等 我使用基于这些坐标的自定义函数 问题是 在 Webkit
  • 升级 @ngrx/Store 时,“Action”类型上不存在属性“payload”

    我有 ngrx store打包在我的 Angular 4 x 应用程序中 并从 v 升级2 2 2 gt v4 0 0 我可以看到迁移注释说 Payload 属性已从 Action 接口中删除 然而 他们给出的例子似乎完全违反直觉 在我看来
  • 整个网页使用一个文件的优点和缺点? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我不知道该怎么表达 但我会尝试一下 我最近开始用面向对象的 PHP 编写我的作品集 我想知道使用内容根据 SQL 数据和 GET 变量
  • 如何从 Android Fragment 禁用或隐藏抽屉布局

    我的应用程序中有 10 个不同的片段 我需要在几个片段中隐藏导航抽屉 抽屉布局 如何从片段访问抽屉布局并隐藏它 我知道我们需要在活动中使用mDrawerLayout setDrawerLockMode DrawerLayout LOCK M
  • VS 2010无法打开源文件“字符串”

    突然之间 我的 VS 2010 项目中的 Intellisense 开始变得疯狂 一切都正确构建 但它无法再找到基本的 C 头文件 如字符串 映射等 它不再识别 std 命名空间 而且通常会变得混乱 代码仍然可以编译 但无论我做什么 我都无
  • 服务器宕机时移动 SVN 存储库

    我的 SVN 服务器死了 我有另一台可以用作 SVN 服务器的机器 还有几台带有原始存储库的工作副本的机器 是否有一种干净的方法可以仅从当前工作副本在新服务器上重新创建存储库 历史是可以被遗忘的 我尝试创建一个新的存储库 破解其 UUID
  • 如何将字符串与整数进行比较

    In SQL Server 2012 我有一组列定义为VARCHAR 这些值是指标的阈值 可以是数字或字符串值 例如 温度的阈值是数字0 and 100 而门的阈值是open and closed 我想测试一个值 ResponseValue
  • 如何使 new FormData() 在 IE 浏览器上工作

    我怎样才能让这个在 IE 上工作 这在 IE 上不起作用 IE 浏览器不支持 new FormData api 是否有其他 api 相当于 IE 中的 new FormData var fd new FormData fd append u
  • Google Apps Script V8 分配给 null 会取消调试

    将变量赋值为 null 会导致调试取消该行的执行 这是重现该问题的测试脚本 function myFunction var a Hallo Logger log a a var b null Logger log b b 调试时 此脚本执行
  • 如何将日期正确转换为 UTC 然后再转换回来?

    我正在努力将 DateTime 转换为 UTC 概念以及所有我无法正确理解的内容 当我得到一个日期时间字符串 比如 7 10 2013 时 我只是这样做 Convert ToDateTime 7 10 2013 ToUniversalTim
  • PyGObject 中的 TreeView 拖放:未调用拖拽数据删除?

    我正在研究如何在 PyGObject 的 TreeView 中进行拖放的示例 我有一些不明白的事情 为什么是drag data delete函数从未被调用 这是独立的示例 from gi repository import Gtk Gdk
  • Google 应用程序脚本在 Google 表单提交后触发两次

    我的脚本在 Google 表单和链接的表格中运行两次时遇到问题 我有一个表单提交触发器 如果我删除此触发器 则脚本根本不会在表单提交上运行 如果我重新添加触发器 它将触发两次 但工作表响应中只有一个表单提交 我想也许我点击了表单提交两次 但
  • 使用对数标度在 R 中实现随机游走 Metropolis Hastings

    Context 我几乎到处寻找 但找不到使用对数尺度的随机游走 Metropolis Hastings 算法的完整实现 通过对数尺度 我的意思是我们正在使用目标分布的对数 通常是后验 为了简单起见 我在这里有一个最小的工作示例R但我也会很高
  • 在选择器列表中使用 @at-root 和 &

    我有一个 CSS 我尝试将其迁移到 SASS 其中包含许多结构 例如 btn primary hover btn primary focus btn primary active btn primary active open dropdo
  • 如何在executeBatch()之前检查Prepared Statement是否有批次?

    我对Java中的Prepared Statement有疑问 因为我对此了解不多 我有一个必须使用PreparedStatement 的用例 但我在编写代码之前只是想 while if preparedStatement setString
  • 如何标记 Perl 源代码?

    我有一些合理的 未混淆的 Perl 源文件 我需要一个标记生成器 它将其分割为标记 并返回每个标记的标记类型 例如对于脚本 print Hello World n 它会返回这样的内容 关键字5字节 空白 1 字节 双引号字符串 17 字节
  • 集成测试中的 MVC 策略覆盖

    我正在为 MVC 应用程序添加集成测试 我们的许多端点都应用了策略 例如 namespace WorkProject Route A Route public class WorkController Controller HttpPost