文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

ASP.NET Core单元测试中如何Mock HttpClient.GetStringAsync()的示例分析

2024-04-02 19:55

关注

ASP.NET Core单元测试中如何Mock HttpClient.GetStringAsync()的示例分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

在 ASP.NET Core 单元测试中模拟HttpClient.GetStringAsync() 的技巧。

问题

下面这个代码

var html = await _httpClient.GetStringAsync(sourceUrl);

如果按正常思路像这样去 Mock HttpClient.GetStringAsync()

var httpClientMock = new Mock<HttpClient>(); httpClientMock     .Setup(p => p.GetStringAsync(It.IsAny<string>()))     .Returns(Task.FromResult("..."));

Moq 框架就会爆

Exception

System.NotSupportedException : Unsupported expression: p => p.GetStringAsync(It.IsAny())Non-overridable members (here: HttpClient.GetStringAsync) may not be used in setup / verification expressions.

解决方法

我们需要 Mock HttpClient 底层使用的 HttpMessageHandler 而不是 HttpClient

var handlerMock = new Mock<HttpMessageHandler>(); var magicHttpClient = new HttpClient(handlerMock.Object);

然后我花了 9.96 分钟研究了 HttpClient.GetStringAsync() 的源代码,发现它最终调用的是 SendAsync()  方法

private async Task<string> GetStringAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken) {     // ...     response = await base.SendAsync(request, cts.Token).ConfigureAwait(false);     // ... }

源代码位置:https://source.dot.net/#System.Net.Http/System/Net/Http/HttpClient.cs,170

因此,我们的 Mock Setup 如下:

handlerMock     .Protected()     .Setup<Task<HttpResponseMessage>>(         "SendAsync",         ItExpr.IsAny<HttpRequestMessage>(),         ItExpr.IsAny<CancellationToken>()     )     .ReturnsAsync(new HttpResponseMessage     {         StatusCode = HttpStatusCode.OK,         Content = new StringContent("the string you want to return")     })     .Verifiable();

现在 Mock 就能运行成功了!

最后附上完整的 UT 代码供参考:

using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Moq; using Moq.Protected; using NUnit.Framework;  namespace Moonglade.Pingback.Tests {     [TestFixture]     public class PingSourceInspectorTests     {         private MockRepository _mockRepository;          private Mock<ILogger<PingSourceInspector>> _mockLogger;         private Mock<HttpMessageHandler> _handlerMock;         private HttpClient _magicHttpClient;          [SetUp]         public void SetUp()         {             _mockRepository = new(MockBehavior.Default);             _mockLogger = _mockRepository.Create<ILogger<PingSourceInspector>>();             _handlerMock = _mockRepository.Create<HttpMessageHandler>();         }          private PingSourceInspector CreatePingSourceInspector()         {             _magicHttpClient = new(_handlerMock.Object);             return new(_mockLogger.Object, _magicHttpClient);         }          [Test]         public async Task ExamineSourceAsync_StateUnderTest_ExpectedBehavior()         {             string sourceUrl = "https://996.icu/work-996-sick-icu";             string targetUrl = "https://greenhat.today/programmers-special-gift";              _handlerMock                 .Protected()                 .Setup<Task<HttpResponseMessage>>(                     "SendAsync",                     ItExpr.IsAny<HttpRequestMessage>(),                     ItExpr.IsAny<CancellationToken>()                 )                 .ReturnsAsync(new HttpResponseMessage                 {                     StatusCode = HttpStatusCode.OK,                     Content = new StringContent($"<html>" +                                                 $"<head>" +                                                 $"<title>Programmer's Gift</title>" +                                                 $"</head>" +                                                 $"<body>Work 996 and have a <a href=\"{targetUrl}\">green hat</a>!</body>" +                                                 $"</html>")                 })                 .Verifiable();             var pingSourceInspector = CreatePingSourceInspector();              var result = await pingSourceInspector.ExamineSourceAsync(sourceUrl, targetUrl);             Assert.IsFalse(result.ContainsHtml);             Assert.IsTrue(result.SourceHasLink);             Assert.AreEqual("Programmer's Gift", result.Title);             Assert.AreEqual(targetUrl, result.TargetUrl);             Assert.AreEqual(sourceUrl, result.SourceUrl);         }     } }

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网行业资讯频道,感谢您对编程网的支持。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯