无法实例化 class 的代理:System.Net.HttpWebRequest。找不到无参数构造函数

Can not instantiate proxy of class: System.Net.HttpWebRequest. Could not find a parameterless constructor

我正在将我的 C# 函数应用程序从 .net 3.1 升级到 6.0`。

当我 运行 我的测试用例时,我发现 1 我的测试用例失败并出现以下错误。

Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: System.Net.HttpWebRequest. Could not find a parameterless constructor.

基本上,我正在尝试模拟 HttpWebRequest,下面是我的一段代码。

var httpWebRequest = new Mock<HttpWebRequest>();

它在 .Net 3.1 中运行良好。我在两个项目中都使用 Moq 版本 4.16.1。

两个 HttpWebRequest 构造函数都已过时,不应再使用。您必须使用静态函数“Create”来创建 HttpWebRequest class:

的新实例

HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("http://www.contoso.com/");

要解决您的问题,请改用 HttpClient class。这个 class 有一个无参数的构造函数。

当 .Net 6 最初发布时,我花了相当多的时间来建立我的单元测试套件。以下是我使用相同的最小起订量版本 4.16.1 执行此操作的方法:

单元测试从基础中获取一个 Moq HttpClientFactoryClass:

public class UnitTests : BaseUnitTest
{
[Fact]
public async Task Should_Return_GetSomethingAsync()
{
    // Arrange
    IHttpClientFactory httpClientFactory = base.GetHttpClientFactory(new Uri("ExternalWebsiteUrlToMockTheResponse"), new StringContent("A Mock Response JSON Object"));
    YourService yourService = new YourService(httpClientFactory);

    // Act
    Something something = yourService.GetSomethingAsync().Result;

    // Assert
    Assert.IsType<Something>(Something);
    //..
}

在 BaseUnitTest.cs Class:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Moq;
using Moq.Protected;

public class BaseUnitTest
{
public IHttpClientFactory GetHttpClientFactory(Uri uri, StringContent content, HttpStatusCode statusCode = HttpStatusCode.OK)
{
    Mock<HttpMessageHandler> httpMsgHandler = new Mock<HttpMessageHandler>();
    httpMsgHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", new object[2]
    {
        ItExpr.IsAny<HttpRequestMessage>(),
        ItExpr.IsAny<CancellationToken>()
    }).ReturnsAsync(new HttpResponseMessage
    {
        StatusCode = statusCode,
        Content = content
    });
    HttpClient client = new HttpClient(httpMsgHandler.Object);
    client.BaseAddress = uri; 
    Mock<IHttpClientFactory> clientFactory = new Mock<IHttpClientFactory>();
    clientFactory.Setup((IHttpClientFactory cf) => cf.CreateClient(It.IsAny<string>())).Returns(client);

    return clientFactory.Object;
}

您的服务 Class 或控制者:

public class YourService : IYourService
{
    private readonly IHttpClientFactory _clientFactory;
    private readonly HttpClient _client;
    public YourService(IHttpClientFactory clientFactory)
    {          
        _clientFactory = clientFactory;
        _client = _clientFactory.CreateClient("YourAPI");
    }

    public async Task<Something> GetSomethingAsync()
    {
        using (var request = new HttpRequestMessage(HttpMethod.Post, _client.BaseAddress))
        {
            request.Content = new StringContent($@"{{""jsonrpc"":""2.0"",""method"":""Something"",""params"": [""{SomethingHash}""],""id"":1}}");

            using (var response = await _client.SendAsync(request))
            {
                //System.Diagnostics.Debug.WriteLine(response?.Content.ReadAsStringAsync()?.Result);

                if (response.IsSuccessStatusCode)
                {
                    using (var responseStream = await response.Content.ReadAsStreamAsync())
                    {
                        var options = new JsonSerializerOptions { IncludeFields = true };
                        var something = await JsonSerializer.DeserializeAsync<Something>(responseStream, options);
                        // Check if the transactions from the address we're looking for...
                        if (something != null)
                        {
                            if (something.result?.from == address)
                            {
                                return something;
                            }
                 } } }
                else {
                    string exceptionMsg = $"Message: {response.Content?.ReadAsStringAsync()?.Result}";
                    throw new YourGeneralException(response.StatusCode, exceptionMsg);
                }
            }
        }
        return null;
    }
}

在你的Program.cs

builder.Services.AddHttpClient("YourAPI", c =>
{
    c.BaseAddress = new Uri("ExternalWebsiteUrlToMockTheResponse");
    c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    c.DefaultRequestHeaders.UserAgent.TryParseAdd("Your Agent");
});

您可以扩展 BaseUnitTest.ccs class 以进行链式测试。