如何在 VB.NET 中模拟 HttpResponseMessage SendAsync?

问题描述 投票:0回答:1

我确实找到了一百篇关于如何在 C# 中执行此操作的帖子,但没有一篇关于如何在 VB.Net 中执行此操作的帖子。每次将这些方法转换为 VB.NET 的尝试都失败了。似乎可以归结为 SendAsync 是“受保护的朋友”这一事实,如以下错误图像所示:

如果您看不到图像,我收到的错误是:“HttpMessageHandler.Protected Friend MustOverride Overloads Function SendAsync(request As HttpRequestMessage, candellationToken As CancellationToken) As Task(Of HttpResponseMessage)”在此上下文中无法访问,因为这是“受保护的朋友”。错误号是 BC30390,这会导致非常有用的 Microsoft 错误页面“抱歉,我们没有关于此 Visual Basic 错误的详细信息”。

首先,这是一个跨越多个部门的庞然大物,更改为 C# 不是一个选择。我正在对业务逻辑的一部分进行单元测试,该逻辑从另一个系统调用 API,然后在返回该数据时执行其他代码并返回结果。测试数据不能依赖从外部 API 返回的结果,因此我需要模拟 API 结果以与我的测试数据匹配。这是我尝试测试的 BL 函数部分:

    Public Sub New(context As IUSASContext, account As IAccount, configurationManager As IDBConfigurationManager)
        _Context = context
        _Account = account
        _AppSettingsConfigManager = configurationManager
        _UserPreferenceHistory = New UserPreferenceHistory(_Context, _Account)
    End Sub


    Public Async Function GetUserPreferenceResponseData(id As Long, httpClient As HttpClient) As Task(Of UserPreferences)
        Dim baseUri = New Uri(AppSettingsHelper.GetValue(AppSettingName.ActivitySummaryApiUri, "", _AppSettingsConfigManager))
        Dim userContentReponse = Await httpClient.GetAsync(New Uri(baseUri, "/api/v1/UserContents"))
        Dim userContentData = Await userContentReponse.Content.ReadAsStringAsync()

        Dim userResponse = Await httpClient.GetAsync(New Uri(baseUri, $"/api/v1/Users/{_Account.CurrentTenant}/{id}"))
        Dim userData = Await userResponse.Content.ReadAsStringAsync()

        Dim userPreferences As UserPreferences = Newtonsoft.Json.JsonConvert.DeserializeObject(Of UserPreferences)(userData)
        userPreferences.SchedulesList = GetUserPreferencesEmailScheduleList()
        userPreferences.UserContentsList = Newtonsoft.Json.JsonConvert.DeserializeObject(Of List(Of Opm.Staffing.Models.ActivitySummary.UserContent))(userContentData)
        userPreferences.Id = id

        Return userPreferences
    End Function

首先,我尝试模拟 HttpClient 本身,并设置“GetAsync”函数,但事实证明这是不可能的。快速的网络搜索证明,普遍的共识是模拟 HttpResponseMessage 并设置“SendAsync”。但是,C# 示例显示将“Protected”放在“Setup”关键字之前,如下例示例

mockHttpMessageHandler.Protected()
                .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
                .ReturnsAsync(new HttpResponseMessage
                {
                    StatusCode = HttpStatusCode.OK,
                    Content = new StringContent("{'name':thecodebuzz,'city':'USA'}"),
                });

当我尝试这样做时,出现以下错误: 如果您看不到该错误,则文本为:“Lambda 表达式无法转换为 'String',因为 'String' 不是委托类型。”

这是我的单元测试的最新版本:

        <TestMethod()> Public Sub GetUserPreferenceResponseData()

        'Arrange
        Dim methodName = System.Reflection.MethodBase.GetCurrentMethod().Name

        Dim asuc As New ActivitySummary.UserContent() With {.UserContentId = 1, .UserContentName = "BB"}
        Dim uc As New List(Of ActivitySummary.UserContent) From {asuc}

 ' the below produces the "Protected Friend" intellesense error
 '_HTTPMessageHandlerMock.Setup(Function(x) x.SendAsync(It.IsAny(Of HttpRequestMessage), It.IsAny(Of Threading.CancellationToken))) _
 .Returns(New HttpResponseMessage With {.Content = New StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(uc))})

 ' the below produces the "String not a Delegate Type " intellesense error
 _HTTPMessageHandlerMock.Protected().Setup(Function(x) x.SendAsync(It.IsAny(Of HttpRequestMessage), It.IsAny(Of Threading.CancellationToken))) _
 .Returns(New HttpResponseMessage With {.Content = New StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(uc))})

        Dim _Client = New HttpClient(_HTTPMessageHandlerMock.Object)

        Dim userPreferencesBL As New UserPreferencesBL(_Context, _Account, _dbConfigManager)
        Dim uid As Integer

        'Action
        Dim result = userPreferencesBL.GetUserPreferenceResponseData(uid, _Client)

        'Assert
        Assert.IsNotNull(result, methodName + " returned null, expected User Preferences.")

    End Sub

将鼠标悬停在“SendAsync”上会显示我上面提到的错误。

我一直在兜圈子,因为改变一件事会破坏另一件事,而我本以为已经解决了。任何帮助将不胜感激。

vb.net moq protected httpresponsemessage sendasync
1个回答
0
投票

这样的东西应该有效:

Dim httpMessageHandlerMock As New Mock(Of HttpMessageHandler)
httpMessageHandlerMock _
    .Protected() _ ' Needs Imports Moq.Protected
    .Setup(Of Task(Of HttpResponseMessage))(
        "SendAsync",
        ItExpr.IsAny(Of HttpRequestMessage),
        ItExpr.IsAny(Of Threading.CancellationToken)) _
    .ReturnsAsync(
        New HttpResponseMessage() With
        {
            .Content = New JsonConvert.SerializeObject(uc))
        })

Dim client = New HttpClient(httpMessageHandlerMock.Object)

请注意,正如评论所说,您需要

Imports Moq.Protected

因为否则

Protected
扩展方法和该 API 的其余部分不可用。

您不能使用具有

Protected
访问权限的 lambda 表达式或其他强类型表达式,因为该方法仅对继承类可见,并且测试或
httpMessageHandlerMock
不是从
HttpMessageHandler
继承的。因此,您需要使用字符串 (
"SendAsync"
) 来标识要重写的方法,并使用
ItExpr
API 来匹配输入参数。

© www.soinside.com 2019 - 2024. All rights reserved.