点击上方蓝字关注“汪宇杰博客”

导语

在 ASP.NET Core 中,当你在 UrlHelperExtensions 类上使用扩展方法时,很难在单元测试中编写Mock。因为Moq框架不支持模拟扩展方法。

问题

例如,我的博客代码中使用了 Url.Page() 方法:

var callbackUrl = Url.Page("/Index", null, null, Request.Scheme);

但是单元测试中,像这样 Mock 就会爆:

var mockUrlHelper = new Mock<IUrlHelper>(MockBehavior.Strict);mockUrlHelper.Setup(x => x.Page("/Index", null, null, It.IsAny<string>())).Returns("callbackUrl").Verifiable();

爆炸现场

System.NotSupportedException : Unsupported expression: x => x.Page("/Index", null, null, It.IsAny<string>())    Extension methods (here: UrlHelperExtensions.Page) may not be used in setup / verification expressions.

解决方法

我们需要 Mock 这个拓展方法调用的底层方法。在本案例中,底层方法是

Microsoft.AspNetCore.Mvc.IUrlHelper.RouteUrl(UrlRouteContext routeContext)

我是怎么知道的呢?很简单,.NET 都已经开源多少年了,直接看一眼源代码就能知道微软如何单元测试 UrlHelperExtensions。

https://source.dot.net/

从微软的代码里复制两个助手方法

private Mock<IUrlHelper> CreateMockUrlHelper(ActionContext context = null)

{

context ??= GetActionContextForPage("/Page");

var urlHelper = _mockRepository.Create<IUrlHelper>();

urlHelper.SetupGet(h => h.ActionContext)

.Returns(context);

return urlHelper;

}

private static ActionContext GetActionContextForPage(string page)

{

return new()

{

ActionDescriptor = new()

{

RouteValues = new Dictionary<string, string>

{

{ "page", page },

}

},

RouteData = new()

{

Values =

{

[ "page" ] = page

}

}

};

}

修改我们的单元测试

var mockUrlHelper = CreateMockUrlHelper();mockUrlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>())).Returns("callbackUrl");

现在单元测试就能顺利跑过了!

完整的单元测试代码见下方供参考:

[Test]

public async Task SignOutAAD()

{

_mockOptions.Setup(m => m.Value).Returns(new AuthenticationSettings

{

Provider = AuthenticationProvider.AzureAD

});

var mockUrlHelper = CreateMockUrlHelper();

mockUrlHelper.Setup(h => h.RouteUrl(It.IsAny<UrlRouteContext>()))

.Returns("callbackUrl");

var ctx = new DefaultHttpContext();

var ctl = CreateAuthController();

ctl.ControllerContext = new() { HttpContext = ctx };

ctl.Url = mockUrlHelper.Object;

var result = await ctl.SignOut();

Assert.IsInstanceOf(typeof(SignOutResult), result);

}

汪宇杰博客

Azure | .NET | 微软 MVP

无广告,不卖课,做纯粹的技术公众号

ASP.NET Core 单元测试:如何Mock Url.Page()相关推荐

  1. Asp.Net Core 单元测试正确姿势

    背景 ASP.NET Core 支持依赖关系注入 (DI) 软件设计模式,并且默认注入了很多服务,具体可以参考 官方文档, 相信只要使用过依赖注入框架的同学,都会对此有不同深入的理解,在此无需赘言. ...

  2. asp.net core设置默认起始页Default Page和重定向

    为什么80%的码农都做不了架构师?>>>    用Asp.Net Core的网站Deploy至IIS,因此找了下,发现两种方法: 添加引用 using System.Threadin ...

  3. ASP.NET Core 单元测试:如何 Mock HttpContext.Features.Get()

    点击上方蓝字关注"汪宇杰博客" 导语 在 ASP.NET Core 里,如果你想单元测试 HttpContext.Features.Get<SomeType>(),这个 ...

  4. 关于单元测试的思考--Asp.Net Core单元测试最佳实践

    https://www.cnblogs.com/yubaolee/p/DotNetCoreUnitTest.html 在我们码字过程中,单元测试是必不可少的.但在从业过程中,很多开发者却对单元测试望而 ...

  5. ASP.NET Core URL Rewrite中间件

    URL重写是基于一个或多个预置规则修改请求URL的行为.URL重写在资源位置和访问地址之间创建了一种抽象,这样二者之间就减少了紧密的联系.URL重写有多种适用的场景: 临时或永久移动或替换服务器资源, ...

  6. ASP.NET Core的Kestrel服务器

    原文地址----Kestrel server for ASP.NET Core By Tom Dykstra, Chris Ross, and Stephen Halter Kestrel是一个基于l ...

  7. ASP.NET Core 管道再探

    几乎任何服务器端处理环境都有自己的直通组件管道,用于检查.重路由或修改传入请求和传出响应.经典 ASP.NET 围绕 HTTP 模块理念进行排列,而 ASP.NET Core 采用基于中间件组件的更现 ...

  8. ASP.NET Core MVC+EF Core从开发到部署

    笔记本电脑装了双系统(Windows 10和Ubuntu16.04)快半年了,平时有时间就喜欢切换到Ubuntu系统下耍耍Linux,熟悉熟悉Linux命令.Shell脚本以及Linux下的各种应用的 ...

  9. ASP.NET Core 对Controller进行单元测试

    单元测试对我们的代码质量非常重要.很多同学都会对业务逻辑或者工具方法写测试用例,但是往往忽略了对Controller层写单元测试.我所在的公司没见过一个对Controller写过测试的.今天来演示下如 ...

最新文章

  1. Cell子刊:微生物组学研究的突破与瓶颈
  2. 3.对角线遍历(LeetCode第498题)
  3. rhel 8.2不识别unicode_基于tensorflow 实现端到端的OCR:二代身份证号识别
  4. Magento微信支付接口开发小记
  5. 手把手教你逼走员工的23种套路,大写的服!
  6. 深度卷积神经网络的高级主题
  7. 计算机电脑用户名,如何改计算机用户名(administrator)
  8. jq富文本_jQuery富文本编辑器Notebook
  9. 如何实现thead固定不动,tbody出现垂直滚动条
  10. 计算机关机界面设置在哪里,电脑怎么设置关机画面
  11. Windows快捷键小记
  12. 重拾Java基础知识:设计模式
  13. Oracle创建数据库连接——DATABASE LINKS
  14. 怎么制作区域分布图,怎么做网点分布图
  15. 损失惨重!数据中心失火,360万个网站下线,Rust游戏25台服务器数据永久丢失...
  16. 使用node-red通过MQTT传送数据
  17. java wmf格式图片转png
  18. 记HP 12c的一个坑
  19. 入门Python必备100道练习题
  20. 我的python入门心得

热门文章

  1. plsql如何执行存储过程_如何理解Spark应用的执行过程
  2. Linux禁止用户登录
  3. [CQOI2012]模拟工厂 题解(搜索+贪心)
  4. hdu - 2586 How far away ?(最短路共同祖先问题)
  5. ASP.NET 连接MySql数据库
  6. Hello, AnnsShadow!
  7. 60个高质量的CSS、XHTML网页布局模板下载
  8. 2010 本年度认证目标:坐沙发的熊
  9. 从基础开始:Qomo OpenProject中的一些关键词
  10. 可转债数据一览表集思录_可转债股票数据一览表