gpt4 book ai didi

c# - 模拟 IHttpClientFactory - xUnit C#

转载 作者:行者123 更新时间:2023-11-30 21:26:23 25 4
gpt4 key购买 nike

我试图在我的项目中构建一个通用的 HTTP 服务(c# with .net core 2.1),我已经按照下面的代码片段 HttpService 完成了它。

我还开始使用它,方法是从我的业务逻辑类调用它,该类使用此通用 PostAsync 方法将 HTTP 调用发布到具有正文内容的第 3 方。效果很好。

但是,当我尝试测试它时,我失败了!实际上,当我尝试调试(测试模式)时,当调试器到达此行 var result = await _httpService.PostAsync("https://test.com/api", content); 在业务类 Processor 中,即使有假对象和模拟,尽管它在没有测试/模拟的 Debug模式下正常工作。

HTTP 服务:

public interface IHttpService
{
Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content);
}

public class HttpService : IHttpService
{
private readonly IHttpClientFactory _httpClientFactory;

public HttpService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}

public async Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content)
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.Timeout = TimeSpan.FromSeconds(3);
var response = await httpClient.PostAsync(requestUri, content).ConfigureAwait(false);
response.EnsureSuccessStatusCode();

return response;
}
}

商务舱:

public class Processor : IProcessor
{
private readonly IHttpService _httpService;

public Processor() { }

public Processor(IHttpService httpService, IAppSettings appSettings)
{
_httpService = httpService;
}

public async Task<HttpResponseMessage> PostToVendor(Order order)
{
// Building content
var json = JsonConvert.SerializeObject(order, Formatting.Indented);
var content = new StringContent(json, Encoding.UTF8, "application/json");

// HTTP POST
var result = await _httpService.PostAsync("https://test.com/api", content); // returns null during the test without stepping into the method PostAsyn itself

return result;
}
}

测试类:

public class MyTests
{
private readonly Mock<IHttpService> _fakeHttpMessageHandler;
private readonly IProcessor _processor; // contains business logic
private readonly Fixture _fixture = new Fixture();

public FunctionTest()
{
_fakeHttpMessageHandler = new Mock<IHttpService>();
_processor = new Processor(_fakeHttpMessageHandler.Object);
}

[Fact]
public async Task Post_To_Vendor_Should_Return_Valid_Response()
{
var fakeHttpResponseMessage = new Mock<HttpResponseMessage>(MockBehavior.Loose, new object[] { HttpStatusCode.OK });

var responseModel = new ResponseModel
{
success = true,
uuid = Guid.NewGuid().ToString()
};

fakeHttpResponseMessage.Object.Content = new StringContent(JsonConvert.SerializeObject(responseModel), Encoding.UTF8, "application/json");

var fakeContent = _fixture.Build<DTO>().Create(); // DTO is the body which gonna be sent to the API
var content = new StringContent(JsonConvert.SerializeObject(fakeContent), Encoding.UTF8, "application/json");

_fakeHttpMessageHandler.Setup(x => x.PostAsync(It.IsAny<string>(), content))
.Returns(Task.FromResult(fakeHttpResponseMessage.Object));

var res = _processor.PostToVendor(fakeContent).Result;
Assert.NotNull(res.Content);
var actual = JsonConvert.SerializeObject(responseModel);
var expected = await res.Content.ReadAsStringAsync();
Assert.Equal(expected, actual);
}
}

最佳答案

您的问题出在模拟设置中:

_fakeHttpMessageHandler.Setup(x => x.PostAsync(It.IsAny<string>(), content))
.Returns(Task.FromResult(fakeHttpResponseMessage.Object));

PostAsync 方法的第二个参数应该是 content,但由于 StringContent 是引用类型,因此您在 mock 中设置的 contentcontent 不同> 你在处理器中创建。如果将其更改为下一个,它应该会按预期工作:

    _fakeHttpMessageHandler.Setup(x => x.PostAsync(It.IsAny<string>(), It.IsAny<StringContent>()))
.Returns(Task.FromResult(fakeHttpResponseMessage.Object));

附言对 PostAsync 的空响应意味着该方法具有默认设置,这意味着它将返回默认值

关于c# - 模拟 IHttpClientFactory - xUnit C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59237827/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com