成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

ASP.NET Core 單元測試之如何 Mock HttpClient.GetStringAsync()

開發(fā) 前端
在 ASP.NET Core 單元測試中模擬HttpClient.GetStringAsync() 的技巧。如果按正常思路像這樣去 Mock HttpClient.GetStringAsync()。

 [[398893]]

本文轉載自微信公眾號「汪宇杰博客」,作者汪宇杰。轉載本文請聯系汪宇杰博客公眾號。

在 ASP.NET Core 單元測試中模擬HttpClient.GetStringAsync() 的技巧。

問題

下面這個代碼

  1. var html = await _httpClient.GetStringAsync(sourceUrl); 

如果按正常思路像這樣去 Mock HttpClient.GetStringAsync()

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

Moq 框架就會爆

Exception

  1. 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

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

然后我花了 9.96 分鐘研究了 HttpClient.GetStringAsync() 的源代碼,發(fā)現它最終調用的是 SendAsync() 方法

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

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

因此,我們的 Mock Setup 如下:

  1. handlerMock 
  2.     .Protected() 
  3.     .Setup<Task<HttpResponseMessage>>( 
  4.         "SendAsync"
  5.         ItExpr.IsAny<HttpRequestMessage>(), 
  6.         ItExpr.IsAny<CancellationToken>() 
  7.     ) 
  8.     .ReturnsAsync(new HttpResponseMessage 
  9.     { 
  10.         StatusCode = HttpStatusCode.OK, 
  11.         Content = new StringContent("the string you want to return"
  12.     }) 
  13.     .Verifiable(); 

現在 Mock 就能運行成功了!

最后附上完整的 UT 代碼供參考:

  1. using System.Net; 
  2. using System.Net.Http; 
  3. using System.Threading; 
  4. using System.Threading.Tasks; 
  5. using Microsoft.Extensions.Logging; 
  6. using Moq; 
  7. using Moq.Protected; 
  8. using NUnit.Framework; 
  9.  
  10. namespace Moonglade.Pingback.Tests 
  11.     [TestFixture] 
  12.     public class PingSourceInspectorTests 
  13.     { 
  14.         private MockRepository _mockRepository; 
  15.  
  16.         private Mock<ILogger<PingSourceInspector>> _mockLogger; 
  17.         private Mock<HttpMessageHandler> _handlerMock; 
  18.         private HttpClient _magicHttpClient; 
  19.  
  20.         [SetUp] 
  21.         public void SetUp() 
  22.         { 
  23.             _mockRepository = new(MockBehavior.Default); 
  24.             _mockLogger = _mockRepository.Create<ILogger<PingSourceInspector>>(); 
  25.             _handlerMock = _mockRepository.Create<HttpMessageHandler>(); 
  26.         } 
  27.  
  28.         private PingSourceInspector CreatePingSourceInspector() 
  29.         { 
  30.             _magicHttpClient = new(_handlerMock.Object); 
  31.             return new(_mockLogger.Object, _magicHttpClient); 
  32.         } 
  33.  
  34.         [Test] 
  35.         public async Task ExamineSourceAsync_StateUnderTest_ExpectedBehavior() 
  36.         { 
  37.             string sourceUrl = "https://996.icu/work-996-sick-icu"
  38.             string targetUrl = "https://greenhat.today/programmers-special-gift"
  39.  
  40.             _handlerMock 
  41.                 .Protected() 
  42.                 .Setup<Task<HttpResponseMessage>>( 
  43.                     "SendAsync"
  44.                     ItExpr.IsAny<HttpRequestMessage>(), 
  45.                     ItExpr.IsAny<CancellationToken>() 
  46.                 ) 
  47.                 .ReturnsAsync(new HttpResponseMessage 
  48.                 { 
  49.                     StatusCode = HttpStatusCode.OK, 
  50.                     Content = new StringContent($"<html>" + 
  51.                                                 $"<head>" + 
  52.                                                 $"<title>Programmer's Gift</title>" + 
  53.                                                 $"</head>" + 
  54.                                                 $"<body>Work 996 and have a <a href=\"{targetUrl}\">green hat</a>!</body>" + 
  55.                                                 $"</html>"
  56.                 }) 
  57.                 .Verifiable(); 
  58.             var pingSourceInspector = CreatePingSourceInspector(); 
  59.  
  60.             var result = await pingSourceInspector.ExamineSourceAsync(sourceUrl, targetUrl); 
  61.             Assert.IsFalse(result.ContainsHtml); 
  62.             Assert.IsTrue(result.SourceHasLink); 
  63.             Assert.AreEqual("Programmer's Gift", result.Title); 
  64.             Assert.AreEqual(targetUrl, result.TargetUrl); 
  65.             Assert.AreEqual(sourceUrl, result.SourceUrl); 
  66.         } 
  67.     } 

 

 

責任編輯:武曉燕 來源: 汪宇杰博客
相關推薦

2021-04-26 14:25:39

ASP.NET Cor單元測試

2009-07-24 11:33:12

MVC單元測試ASP.NET

2009-07-23 16:29:06

ASP.NET單元測試

2024-07-29 12:12:59

2009-08-21 16:09:04

HttpContextPath屬性

2017-03-23 16:02:10

Mock技術單元測試

2023-07-04 08:26:15

2009-07-28 17:17:19

ASP.NET概述

2021-03-17 09:45:31

LazyCacheWindows

2021-02-06 21:40:13

SignalR通訊TypeScript

2021-02-02 16:19:08

Serilog日志框架

2021-11-01 14:52:38

ElasticSear索引SQL

2021-03-04 11:10:29

容器化Docker虛擬機

2021-03-10 09:40:43

LamarASP容器

2021-02-03 13:35:25

ASPweb程序

2021-02-28 20:56:37

NCache緩存框架

2021-01-07 07:39:07

工具接口 Swagger

2021-03-03 22:37:16

MediatR中介者模式

2021-01-28 22:39:35

LoggerMessa開源框架

2021-01-31 22:56:50

FromServiceASP
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产网站在线 | 99精品在线观看 | 四虎影院新网址 | 日韩免费成人av | 精品国产91乱码一区二区三区 | 91日韩| 精品福利在线视频 | 亚洲人人 | 国产一区不卡在线观看 | 亚洲国产电影 | 欧美精品一区二区三区四区 在线 | 亚洲国产成人精品女人久久久 | 成人不卡| 中文字幕色站 | 日韩欧美一级精品久久 | 综合自拍 | 国产精品久久精品 | 久久久久国产精品一区二区 | 九九热久久免费视频 | 最新中文字幕 | 嫩草视频在线免费观看 | 操射视频| 一区二区三区在线看 | 欧美一区二区三区在线播放 | 中文字幕人成乱码在线观看 | 一区二区三区欧美 | 婷婷激情综合 | 在线一区 | 黄色大片在线视频 | 成人精品一区二区三区 | 欧美视频区 | 青青激情网 | 手机av在线 | 欧美一区不卡 | 91人人在线| 日韩一区二区三区在线观看 | 草逼网站 | 国产毛片视频 | 一区在线免费视频 | 伊人网站在线 | 一区二区三区四区五区在线视频 |