您好,登錄后才能下訂單哦!
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("..."));
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); } } }
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。