#c# #.net #testing #pact-net
#c# #.net #тестирование #пакт-нетто
Вопрос:
Я пытаюсь написать контрактный тест, используя PactNet
для следующего метода:
public async Task<IEnumerable<Models.RefData.Instrument> GetInstruments(string issuerCountry, string instrumentType)
{
ValidateNotNullOrWhiteSpaceParameter(issuerCountry, nameof(issuerCountry));
ValidateNotNullOrWhiteSpaceParameter(instrumentType, nameof(instrumentType)); ;
var queryString = $"instruments?issuerCountry={HttpUtility.UrlEncode(issuerCountry)}amp;instrumentType={HttpUtility.UrlEncode(instrumentType)}";
int pageNo = 0;
int pageSize = 20;
_logger.LogDebug($"GetInstruments Request:{queryString}");
var httpResponseMessage = await _client.GetAsync(queryString $"amp;page={pageNo}amp;size={pageSize}");
_logger.LogDebug($"GetInstruments Response Status Code:{httpResponseMessage.StatusCode}");
switch (httpResponseMessage.StatusCode)
{
case HttpStatusCode.OK:
var content = await httpResponseMessage.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<GetInstrumentsResponse>(content);
// if there are no results, return Empty
if (result.Metadata.TotalElements == 0)
{
return Enumerable.Empty<Models.RefData.Instrument>();
}
var instruments = new List<Models.RefData.Instrument>();
instruments.AddRange(result.Embedded.Instruments);
for (pageNo = 1; pageNo < result.Metadata.TotalPages; pageNo )
{
var innerQueryString = queryString $"amp;page={pageNo}amp;size={pageSize}";
_logger.LogDebug($"GetInstruments Request Additional Page:{innerQueryString}");
var httpResponseMessage2 = await _client.GetAsync(innerQueryString);
if (httpResponseMessage2.StatusCode != HttpStatusCode.OK)
{
_logger.LogError($"The requested page number {pageNo} gets response error {httpResponseMessage2.StatusCode.ToString()}.");
throw new UnexpectedResponseException(httpResponseMessage.StatusCode);
}
var content2 = await httpResponseMessage2.Content.ReadAsStringAsync();
var result2 = JsonConvert.DeserializeObject<GetInstrumentsResponse>(content2);
if (result2.Embedded.Instruments != null amp;amp; result2.Embedded.Instruments.Any())
{
instruments.AddRange(result2.Embedded.Instruments);
}
}
if (instruments.Count != result.Metadata.TotalElements)
{
_logger.LogWarning($"Total number of instruments is different from MetaData. MetaData states {result.Metadata.TotalElements}, however only {instruments.Count} instruments retrieved.");
}
_logger.LogDebug($"GetInstruments Result:{instruments.ToJson()}");
return instruments;
default:
throw new UnexpectedResponseException(httpResponseMessage.StatusCode);
}
}
Я создал следующее ConsumerPactTests.cs
и ConsumerPactClassFixture.cs
использую это в качестве руководства.
public class ConsumerPactTests : IClassFixture<ConsumerPactClassFixture>
{
private IMockProviderService _mockProviderService;
private string _mockProviderServiceBaseUri;
public ConsumerPactTests(ConsumerPactClassFixture fixture)
{
_mockProviderService = fixture.MockProviderService;
_mockProviderService.ClearInteractions(); //NOTE: Clears any previously registered interactions before the test is run
_mockProviderServiceBaseUri = fixture.MockProviderServiceBaseUri;
}
[Fact]
public void ItHandlesInvalidDateParam()
{
// Arange
var invalidRequestMessage = "issuerCountry or instrumentType is not valid";
_mockProviderService.Given("There is data")
.UponReceiving("A invalid GET request for Date Validation with invalid date parameter")
.With(new ProviderServiceRequest
{
Method = HttpVerb.Get,
Path = "/api/v2",
Query = "issuerCountry=USAamp;instrumentType=foo"
})
.WillRespondWith(new ProviderServiceResponse
{
Status = 400,
Headers = new Dictionary<string, object>
{
{ "Content-Type", "application/json; charset=utf-8" }
},
Body = new
{
message = invalidRequestMessage
}
});
// Act
RefDataHttpService sut = new RefDataHttpServiceBuilder().Build();
var result = sut.GetInstruments("USA", "foo").GetAwaiter().GetResult();
var resultBodyText = result.GetEnumerator();
// Assert
Assert.NotNull(resultBodyText);
}
}
public class ConsumerPactClassFixture : IDisposable
{
public IPactBuilder PactBuilder { get; private set; }
public IMockProviderService MockProviderService { get; private set; }
public int MockServerPort { get { return 9222; } }
public string MockProviderServiceBaseUri { get { return String.Format("http://localhost:{0}", MockServerPort); } }
public ConsumerPactClassFixture()
{
var pactConfig = new PactConfig
{
SpecificationVersion = "2.0.0",
PactDir = @"..........pacts",
LogDir = @".pact_logs"
};
PactBuilder = new PactBuilder(pactConfig);
PactBuilder.ServiceConsumer("Consumer")
.HasPactWith("Provider");
MockProviderService = PactBuilder.MockService(MockServerPort);
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// This will save the pact file once finished.
PactBuilder.Build();
}
disposedValue = true;
}
}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
}
#endregion
}
Когда я запускаю свой тест, я получаю эту ошибку:
тест dotnet —фильтр «FullyQualifiedName=Связь.Издатель.Тесты.ContractTest.ConsumerPactTests.ItHandlesInvalidDateParam»
Тестовый запуск для c:WorkspaceprodtestBond .Издатель.Тесты bin Debug netcoreapp3.1 Связь.Издатель.Tests.dll (.NETCoreApp, версия = v3.1) Microsoft (R) Средство командной строки для выполнения тестов версии 16.7.0 Авторское право (c) Корпорация Microsoft. Все права защищены.
Начиная выполнение теста, пожалуйста, подождите…
Всего 1 тестовый файл соответствовал указанному шаблону. [xUnit.net 00:00:10.95] Связь.Издатель.Тесты.ContractTest.ConsumerPactTests.ItHandlesInvalidDateParam [СБОЙ] X связь.Издатель.Тесты.ContractTest.ConsumerPactTests.Сообщение об ошибке ItHandlesInvalidDateParam [4s 196 мс]: System.Net.Http.HttpRequestException : не удалось установить соединение, поскольку целевая машина активно отказалась от него. —- System.Net.Sockets.Исключение SocketException: не удалось установить соединение, поскольку целевая машина активно отказалась от него. Трассировка стека: в System.Net.Http.ConnectHelper.ConnectAsync (строковый хост, порт Int32, CancellationToken CancellationToken) в System.Net.Http.HTTPConnectionPool.ConnectAsync (запрос HttpRequestMessage, логическое значение allowHttp2, CancellationToken CancellationToken) в System.Net.Http.HTTPConnectionPool.Создайте http11connectionasync(запрос HttpRequestMessage, CancellationToken CancellationToken) в System.Net.Http.HTTPConnectionPool.Получить httpconnectionasync(запрос HttpRequestMessage, CancellationToken CancellationToken) в System.Net.Http.HTTPConnectionPool.SendWithRetryAsync (запрос HttpRequestMessage, логическое значение doRequestAuth, CancellationToken CancellationToken) в системе.Net.Http.RedirectHandler.SendAsync (запрос HttpRequestMessage, CancellationToken CancellationToken) при подключении.Издатель.HttpMessageHandlers.UnoAuthorisationHeaderMessageHandler.SendAsync (запрос HttpRequestMessage, CancellationToken CancellationToken) в c:WorkspaceusprodsrcBond .Publisher HttpMessageHandlers UnoAuthorisationHeaderMessageHandler.cs: строка 37 в System.Net.Http.HttpClient.Завершите отправку sendasyncbuffered(Task`1 sendTask, запрос HttpRequestMessage, CancellationTokenSource cts, Boolean disposeCts) при подключении.Издатель.Услуги.RefDataHttpService.GetInstruments(String issuerCountry, String instrumentType) в c:WorkspaceprodsrcBond .Publisher Services RefDataHttpService.cs: строка 52 в связи.Издатель.Тесты.ContractTest.ConsumerPactTests.ItHandlesInvalidDateParam() в c:WorkspaceprodtestBond .Издатель.Тесты ContractTestConsumerPactTests.cs:строка 52 —— Внутренняя трассировка стека —— в System.Net.Http.ConnectHelper.ConnectAsync (строковый хост, порт Int32, CancellationToken CancellationToken)
Не удалось выполнить тест.
Я подозреваю, что это может быть какая-то проблема с аутентификацией, UnoAuthorisationHeaderMessageHandler.cs
связанная с этим. Что я сделал не так с этим?
Ответ №1:
Для меня путь был слишком длинным. Когда я переместил проект в папку ближе к C: , тест был запущен.
Ответ №2:
System.Net.Sockets.Исключение SocketException : не удалось установить соединение, поскольку целевая машина активно отказалась от него. обычно это происходит, когда сервер не прослушивает отправляемый вами URL-адрес.
Проверьте, запущена ли служба ruby (запускает ее тестовый запуск), вы должны увидеть это в диспетчере задач в Visual Studio
Предупредительно, прежде чем вы вызовете pactBuilder.Build (), вы должны иметь возможность выполнить HTTP-запрос через PostMan для http://localhost:9222/instruments …