模拟会话在 MVC 5 中不起作用

2024-02-24

我将值存储在正在测试的控制器操作的会话中。我读过几篇关于如何模拟会话的文章,我正在尝试实现 Milox 的答案在单元测试中设置 httpcontext 当前会话 https://stackoverflow.com/questions/9624242/setting-the-httpcontext-current-session-in-unit-test/10126711#10126711。但当我深入研究Locals | this | base | HttpContext Sessions仍然为 null,并且在设置 Session 变量时测试失败并出现 Null Reference 异常HttpContext.Session["BsAcId"] = vM.BusAcnt.Id;

这是有效的生产代码。vM.BusAcnt.Id返回一个有效的int如果我用一个替换它int值测试仍然失败,因为Session为 null,因此不能在其中存储任何值。

我正在使用 MVC5、EF6 以及最新版本的 xUnit、Moq 和 Resharper 测试运行程序。

Action:

public ActionResult Details(int id)
{
  var vM = new BusAcntVm();
  vM.BusAcnt = _db.BusAcnts.FirstOrDefault(bA => bA.Id == id);

  if ((User.IsInRole("Admin"))) return RedirectToAction("Action");

  HttpContext.Session["BsAcId"] = vM.BusAcnt.Id;

  return View(vM);
}

模拟助手:

  public static class MockHelpers
  {
    public static HttpContext FakeHttpContext()
    {
      var httpRequest = new HttpRequest("", "http://localhost/", "");
      var stringWriter = new StringWriter();
      var httpResponce = new HttpResponse(stringWriter);
      var httpContext = new HttpContext(httpRequest, httpResponce);

      var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(),
                                              new HttpStaticObjectsCollection(), 10, true,
                                              HttpCookieMode.AutoDetect,
                                              SessionStateMode.InProc, false);

      httpContext.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
                                  BindingFlags.NonPublic | BindingFlags.Instance,
                                  null, CallingConventions.Standard,
                                  new[] { typeof(HttpSessionStateContainer) },
                                  null)
                          .Invoke(new object[] { sessionContainer });

      return httpContext;
    }
  }

Test:

[Fact] 
public void AdminGetBusAcntById()
{
  HttpContext.Current = MockHelpers.FakeHttpContext();
  var mockMyDb = MockDbSetup.MockMyDb();
  var controller = new BusAcntController(mockMy.Object);
  var controllerContextMock = new Mock<ControllerContext>();
  controllerContextMock.Setup( x => x.HttpContext.User.
    IsInRole(It.Is<string>(s => s.Equals("Admin")))).Returns(true);
  controller.ControllerContext = controllerContextMock.Object;

  var viewResult = controller.Details(1) as ViewResult;
  var model = viewResult.Model as BusAcntVm;

  Assert.NotNull(model);
  Assert.Equal("Company 1", model.CmpnyName);
}

Milox 的代码似乎有意义,但我无法让它工作。 我错过了什么吗? MVC5 中是否有更改破坏了此代码?

解决方案:

实施达林的回答。我现在有一个会话来写入值(尽管这些值实际上并未写入其中,但出于测试目的不需要这样做)并且测试通过。

Test:

[Fact] 
public void AdminGetBusAcntById()
{
  var mockMyDb = MockDbSetup.MockMyDb();
  var controller = new BusAcntController(mockMy.Object);
  var context = new Mock<HttpContextBase>();
  var session = new Mock<HttpSessionStateBase>();
  var user = new GenericPrincipal(new GenericIdentity("fakeUser"), new[] { "Admin" });
  context.Setup(x => x.User).Returns(user);
  context.Setup(x => x.Session).Returns(session.Object);
  var requestContext = new RequestContext(context.Object, new RouteData());
  controller.ControllerContext = new ControllerContext(requestContext, controller);


  var viewResult = controller.Details(1) as ViewResult;
  var model = viewResult.Model as BusAcntVm;

  Assert.NotNull(model);
  Assert.Equal("Company 1", model.CmpnyName);
}

在你的单元测试中你已经设置了HttpContext.Current = MockHelpers.FakeHttpContext();但 ASP.NET MVC 根本不使用这个静态属性。把...忘了吧HttpContext.Current在 ASP.NET MVC 中。它是遗留的且单元测试不友好(是的,在您的情况下,您仅在单元​​测试中使用它,但 ASP.NET MVC 不使用它,这就是您的代码无法工作的原因)。

重点是 ASP.NET MVC 正在使用 HttpContextBase、HttpRequestBase、HttpResponseBase、HttpSessionStateBase 等抽象,您可以在单元测试中轻松模拟这些抽象。

我们来看一个控制器示例:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        if ((this.User.IsInRole("Admin")))
        {
            return RedirectToAction("Action");
        }

        this.HttpContext.Session["foo"] = "bar";

        return View();
    }
}

以及通过使用 Moq 模拟所需的抽象来实现相应的单元测试:

// arrange
var controller = new HomeController();
var context = new Mock<HttpContextBase>();
var session = new Mock<HttpSessionStateBase>();
var user = new GenericPrincipal(new GenericIdentity("john"), new[] { "Contributor" });
context.Setup(x => x.User).Returns(user);            
context.Setup(x => x.Session).Returns(session.Object);
var requestContext = new RequestContext(context.Object, new RouteData());
controller.ControllerContext = new ControllerContext(requestContext, controller);

// act
var actual = controller.Index();

// assert
session.VerifySet(x => x["foo"] = "bar");
...

如果你想进入User.IsInRole("Admin")条件下,您所要做的就是为被模拟的身份提供适当的角色。

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

模拟会话在 MVC 5 中不起作用 的相关文章

  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 使用会话 php 创建 cookie?

    我使用会话来登录我网站中的用户 问题是 我想让用户remember密码 因此关闭 打开浏览器后他们不需要再次登录 我需要使用 cookie 和 session 来实现它吗 my code user POST user pass POST p
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • PHPUnit - 模拟 S3Client 无法正常工作

    库 aws aws sdk php 2 PHP 版本 PHP 5 4 24 cli 作曲家 json require php gt 5 3 1 aws aws sdk php 2 require dev phpunit phpunit 4
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写

随机推荐

  • 如何使用 POI 解析 Excel 文件中的 UTF-8 字符

    我一直在使用 POI 成功解析 XLS 和 XLSX 文件 但是 我无法从 Excel 电子表格中正确提取特殊字符 例如中文或日文等 UTF 8 编码字符 我已经弄清楚如何从 UTF 8 编码的 csv 或制表符分隔文件中提取数据 但对 E
  • Twitter Bootstrap 嵌套网格放置列

    这可以在 Twitter Bootstrap 中使用相同的标记通过操作行 列类来完成吗 我已经为不同的尺寸设置了单独的标记 理想情况下 我想要一个标记 并使其针对较小的屏幕适当折叠 大视野 Two One
  • 支持作业批处理的排队系统(例如,一名工人同时处理多个作业)

    我正在寻找一个可以支持以下场景的排队系统 客户端添加一个作业 检查某个特定 url URL1 有多少 Facebook 点赞 客户端添加了另一个作业 检查 URL2 的相同信息 一名工作人员从队列中选取 1 到 50 个工作 网址 例如 如
  • VS Code Code Runner 不适用于 virtualenvs

    我无法让 Code Runner 扩展与 virtualenvs 一起使用 每当我尝试运行导入仅安装在 virtualenv 中而不是全局 Python 安装中的库的代码时 我都会收到导入错误 在终端中运行完全相同的代码是可行的 我使用的是
  • 生成 BKS 密钥库并存储应用程序密钥

    我应该创建一个 BKS 密钥库并存储一个私有应用程序密钥 该密钥是一个 48 个字符长的字符串 我还有一个 JCEKS 密钥库 其中已包含此密钥值 如果我尝试使用 portecle 工具转换为 BKS 类型密钥库 则密钥条目会丢失 我是 J
  • 为什么我的程序集需要按特定顺序加载?

    我正在编写一个简单的插件并偶然发现contractType IsAssignableFrom pluginType https msdn microsoft com en us library system type isassignabl
  • 为 nltk 解析树生成语法规则

    如果我有这句话 Mary saw a dog 以及以下内容 pos tags NNP VBD DT NN 是否可以生成这句话的语法规则 以便可以生成解析树 下面的语法是使用的语法规则nltk parse cfg sent Mary saw
  • R 中的 strptime 错误:输入字符串太长

    我似乎无法将数据从 csv 转换为正确的日期类 我使用的是包含 1033 个日期的 csv 我已将 CSV 保存为 YYYYMMDD 格式 这是我导入 csv 的代码 似乎有效 bd lt read csv birthdaysExample
  • 用其内容替换组件 - 角度 2 [重复]

    这个问题在这里已经有答案了 我正在寻找一种方法来拥有仅以其内容呈现的组件 例如 给定组件 Component selector my cmp template div my cmp div class MyComponent 使用 angu
  • Google Analytics 缺少analytics.js 脚本

    我被困在复制谷歌分析跟踪代码问题上 看起来 Google Tag Assistant 没有考虑我从为网站生成的 GA 跟踪 JS 中复制的代码 该网站位于http www orchid co nz http www orchid co nz
  • 如何让用户保持登录状态?迅速

    我正在使用 firebase 进行登录 我需要知道如何保持登录状态直到注销 我听说过 UserDefaults 但我不确定如何使用它 这是我的登录视图控制器 import FirebaseAuth import FirebaseFirest
  • strip_tags 和 html_entity_decode 组合无法按预期工作

    从昨天起我一直在与这个问题作斗争 不幸的是没有任何效果 不完全是 我找到了某种解决方法 经过一些研究和重读文档后我仍然有点目瞪口呆和困惑 假设有一个丑陋的字符串 它已经有正确的 html 编码的特殊字符 像这样 exampleString
  • 是否可以在没有 Axon Server Enterprise 的情况下扩展 Axon Framework

    是否可以在没有 Axon Server 的情况下扩展 Axon Framework企业 我有兴趣使用 Axon 创建原型 CQRS 应用程序 但最终的可部署系统必须免收许可费用 如果 Axon Framework 无法使用免费软件扩展到六个
  • Java Android 激光条码扫描器

    我正在尝试开发一个能够读取条形码 1d 而不是 qr 的应用程序 真正的问题是 常见的条形码阅读器软件非常有用 但它们似乎太慢 无法作为非常频繁和常见的功能使用 这些条形码相当长 有 20 30 位数字 对于 zxing 等应用程序来说似乎
  • 从java中的plsql函数获取返回的记录类型

    我有一个plsql返回记录类型的函数challan rec create or replace package xx bal api as type challan rec is record challan number varchar2
  • THREE.js JSONLoader 回调

    在 THREE js 中 如果我多次调用 JSONLoader 来加载多个对象 如下所示 简化示例 function init var loader new THREE JSONLoader loader load mesh1 js cre
  • React form onChange->setState 落后一步

    我在构建网络应用程序时遇到了这个问题 我在这个中复制了它jsfiddle http jsfiddle net terda12 270Lf0x9 本质上 我想要一个输入来调用this setState message input val 每次
  • Git/SVN 用于 asp.net 开发而不是 VSS?

    在工作中 我们使用ASP net 2 0和VSS VSS 是一个野兽 我们不断地遇到人们检查文件的问题 而且没有分支 让它变得疯狂 我知道 SVN GIT 主要由开源开发人员使用 那么 ASP NET 开发人员使用它有什么缺点吗 我一直在内
  • 如何使用MomentJS将自定义日期设置为react-datepicker的DatePicker?

    我已将日期存储在数据库中 我可以成功获取日期 但是当涉及到将任何特定日期设置为 DatePicker 时反应日期选择器 https www npmjs com package react datepicker 我无法设定那个日期 这是我用来
  • 模拟会话在 MVC 5 中不起作用

    我将值存储在正在测试的控制器操作的会话中 我读过几篇关于如何模拟会话的文章 我正在尝试实现 Milox 的答案在单元测试中设置 httpcontext 当前会话 https stackoverflow com questions 96242