我正在使用 Moq 包为我的服务编写单元测试。
我在嘲笑
HttpMessageHandler
为了嘲笑HttpClient
但我收到了这个运行时间错误消息
System.InvalidOperationException:处理程序未返回响应 留言。
这是我的服务方法
public async Task<PaymentDataResponse> PaymentRequest(double amount, string mobileNo)
{
var client = GetClient(mobileNo);
var request = new PaymentRequest()
{
Amount = amount,
CellNumber = SuitablePhoneNumber(mobileNo),
TerminalId = _paymentInfoSetting.TerminalId,
RedirectUrl = _paymentInfoSetting.RedirectUrl
};
var response = await client.PostAsJsonAsync(_paymentInfoSetting.TokenPath, request, new System.Text.Json.JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
if (!response.IsSuccessStatusCode)
{
throw new PaymentException();
}
var responseModel = await response.Content.ReadFromJsonAsync<PaymentResponse>();
return responseModel.Data;
}
private HttpClient GetClient(string phoneNumber)
{
var client = _httpClientFactory.CreateClient();
client.BaseAddress = new Uri(_paymentInfoSetting.BaseUrl);
client.DefaultRequestHeaders.Add("apiKey", _paymentInfoSetting.ApiKey);
client.DefaultRequestHeaders.Add("mobile", phoneNumber);
return client;
}
这是我的单元测试:
[Fact]
public async Task PaymentRequest_ShouldReturnCorrectData()
{
// Arrange
var amount = _fixture.Create<double>();
var mobileNo = _paymentInfoSetting.PhoneNumber;
var paymentRequest = _fixture.Build<PaymentRequest>()
.With(q => q.Amount, amount).With(q => q.TerminalId, _paymentInfoSetting.TerminalId).With(q => q.RedirectUrl, _paymentInfoSetting.RedirectUrl)
.With(q => q.CellNumber, mobileNo)
.Create();
var paymentDataResponse = _fixture.Create<PaymentDataResponse>();
var paymentResponse = _fixture.Build<PaymentResponse>().With(q => q.Data, paymentDataResponse).Create();
var response = new HttpResponseMessage(HttpStatusCode.OK);
// response.Content = new StringContent(JsonConvert.SerializeObject(paymentResponse), Encoding.UTF8, "application/json");
response.Content = JsonContent.Create(paymentRequest, options: new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
var handler = new Mock<HttpMessageHandler>();
// config 1
//handler.Protected()
// .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
// .ReturnsAsync(response);
// config 2
//handler.Protected()
// .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.Is<HttpRequestMessage>(req =>
// req.Content.ReadAsStringAsync().Result == JsonConvert.SerializeObject(paymentRequest)), ItExpr.IsAny<CancellationToken>())
// .ReturnsAsync(response);
// config 3
handler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.Is<HttpRequestMessage>(req =>
req.Content == JsonContent.Create(paymentRequest, null, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })
), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(response);
var httpClient = new HttpClient(handler.Object);
_httpClientFactoryMock.Setup(q => q.CreateClient(It.IsAny<string>())).Returns(httpClient);
// Act
var result = await _service.PaymentRequest(amount, mobileNo);
var resultJson = JsonConvert.SerializeObject(result);
var paymentDataResponseJson = JsonConvert.SerializeObject(paymentDataResponse);
// Assert
_httpClientFactoryMock.Verify(q => q.CreateClient(It.IsAny<string>()), Times.Once);
resultJson.ShouldBe(paymentDataResponseJson);
}
config 1 正在工作,但我想设置特定请求,所以我尝试 config 2,3 但出现错误。
我用嘲笑来修复它
HttpRequestMessage
var httpRequestMessage = _fixture.Build().With(q => q.Content, JsonContent.Create( paymentRequest, It.IsAny(), It.IsAny())).Create();
var handler = new Mock();
handler.Protected().Setup