Тест интеграции с XUnit, насмешливый внутренний Http-запрос при использовании сквозного теста вызова APIC#

Место общения программистов C#
Ответить
Anonymous
 Тест интеграции с XUnit, насмешливый внутренний Http-запрос при использовании сквозного теста вызова API

Сообщение Anonymous »

У меня есть класс, содержащий HttpClient, который отправляет запрос:

Код: Выделить всё

public class PaPdfApiService : IPaPdfApiService
{
private readonly HttpClient _httpClient;
private readonly ILogger
 _logger;

public PaPdfApiService(HttpClient httpClient, ILogger logger)
{
_httpClient = httpClient;
_logger = logger;
}

public async Task GetDataAsync(string endpoint)
{
HttpResponseMessage response = await _httpClient.GetAsync(endpoint);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}

public async Task PostDataAsync(string endpoint, TRequest requestData)
{
string content = JsonConvert.SerializeObject(requestData, new JsonSerializerSettings
{
DateFormatString = "yyyy-MM-dd",
Formatting = Formatting.Indented,
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
byte[] buffer = Encoding.UTF8.GetBytes(content);
HttpContent httpContent = new ByteArrayContent(buffer);
httpContent.Headers.ContentType = new MediaTypeHeaderValue(MediaTypeNames.Application.Json);

HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, endpoint);
message.Content = httpContent;

_logger.LogInformation("PostDataAsync for endpoint : {endpoint}, content: {@content}", endpoint, content);
HttpResponseMessage responseMessage = await _httpClient.SendAsync(message);

// Check for success status code
if (responseMessage.IsSuccessStatusCode)
{
// Read the response content
string responseContent = await responseMessage.Content.ReadAsStringAsync();
_logger.LogInformation("PostDataAsync was success with response : {responseContent}", responseContent);

return responseContent;
}
else
{
_logger.LogError("PostDataAsync had failed with response status: {StatusCode}, body: {@body}", responseMessage.StatusCode, responseMessage.Content.ReadAsStringAsync());

// Handle error
throw new HttpRequestException($"Error: {responseMessage.Content.ReadAsStringAsync()}");
}
}
}
Я хочу заменить этот вызов:

Код: Выделить всё

HttpResponseMessage responseMessage = await _httpClient.SendAsync(message);
в моем интеграционном тесте — чтобы предотвратить тестирование внешнего источника.
Запуск кода содержит эту настройку:

Код: Выделить всё

services.AddHttpClient(client =>
{
client.BaseAddress = new Uri(pdfGeneratorSettings.BaseAddress);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes($"{pdfGeneratorSettings.UserName}:{pdfGeneratorSettings.Password}")));
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
return handler;
});
Я пытался имитировать ответ на вызов, чтобы вернуть упорядоченный результат из моего тестового класса:

Код: Выделить всё

public class PersonalAgreementModuleTests : IClassFixture
{
private readonly AuthenticationModuleTests _authModuleTests;
private readonly HttpClient _client;
private readonly CustomWebApplicationFactory _factory;

public PersonalAgreementModuleTests(CustomWebApplicationFactory factory)
{
_factory = factory;

_authModuleTests = new AuthenticationModuleTests(factory);

_factory.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
// Remove the existing HttpClient and PaPdfApiService registration
var serviceDescriptor = services.FirstOrDefault(d =>  d.ServiceType == typeof(IPaPdfApiService));
if (serviceDescriptor != null)
{
services.Remove(serviceDescriptor);
}

// Mock HttpMessageHandler
var mockHttpHandler = new Mock();
mockHttpHandler.Protected()
.Setup(
"SendAsync",
ItExpr.Is(req =>
req.Method == HttpMethod.Post), // Match specific endpoint
ItExpr.IsAny())
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(JsonConvert.SerializeObject("5555"), Encoding.UTF8, MediaTypeNames.Application.Json)
});

// Add a mocked HttpClient to IPaPdfApiService
services.AddHttpClient()
.ConfigureHttpClient(client =>
{
client.BaseAddress = new Uri("https://api.10xhealthsystem.dev/");
})
.ConfigurePrimaryHttpMessageHandler(() => mockHttpHandler.Object);
});
});

_client = _factory.CreateClient();
// Register the mocked HttpClient with a name to ensure compatibility

}

[Fact]
public async void Test_FillHealthHistoryQuestionnairePA_Ok()
{

// Arrange

// Authenticate and get the JWT token
var jwtToken = await _authModuleTests.GetAuthToken();

// Add the token to the Authorization header
_client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", jwtToken);

var data = new HealthHistoryQuestionnaireData {
AccountId = "3456789",
PatientAgreementConfigurationId = "3456",
PatientAgreementId = "2345",
SignedDate = DateTime.Now,
};
var mockPatientInfo = new HealthHistoryQuestionnaire
{
PatientHeight = "5'10\"",
PatientWeight = "170 lbs",
PatientGender = "Male",
PatientCellPhone = "123-456-7890"

};

data.Questionnaire = mockPatientInfo;

var context = new StringContent(System.Text.Json.JsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
// Act
var response = await _client.PostAsync($"/api/personal-agreement/questionnaire/health-history", context);

// Assert
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);

var responseContent = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize(responseContent, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
Когда я отлаживаю текстовый проводник представления кода, я вижу, что внутренний SendAsync вернул 400, неверный запрос - потому что вызывается настоящий запрос.
Что не так в приведенном выше издевательстве, которое не позволяет этому ложному сервису заменить исходный запрос?

Подробнее здесь: https://stackoverflow.com/questions/793 ... i-call-end
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»