public async void SecondRequestWithSameCurrencyShouldBeFromCache()
        {
            // Arrange
            //
            var handler = new Mock <HttpMessageHandler>();
            var currencyConverterClientMock = new Mock <CurrencyConverterClient>(
                MockBehavior.Loose, null, handler.CreateClient(), null, null);

            currencyConverterClientMock
            .Setup(_ => _.RequestCurrencyConverter("USD", "CHF"))
            .Returns(() => Task.FromResult(new ExchangeRateInfo
            {
                ExchangeRate  = (decimal)1.1,
                RequestStatus = new RequestStatus(RequestStatusCode.Ok)
            }))
            .Verifiable();

            var webRequestProvider = new ExchangeRateCacheStrategy(
                TestHelper.GetLoggerMock <ExchangeRateCacheStrategy>().Object,
                currencyConverterClientMock.Object, null,
                TestHelper.GetFaceSettings(), TestHelper.GetMetricsMock().Object);

            // Act
            //
            var result1 = await webRequestProvider.GetExchangeRate("USD", "CHF");

            var result2 = await webRequestProvider.GetExchangeRate("USD", "CHF");

            // Assert
            //
            currencyConverterClientMock.Verify(_ => _.RequestCurrencyConverter("USD", "CHF"), Times.Once);
            Assert.Equal((decimal)1.1, result1.ExchangeRate);
            Assert.Equal((decimal)1.1, result2.ExchangeRate);
        }
        public async void ExchangeRateWithErrorShouldFallbackAndProvideLogRecord()
        {
            // Arrange
            //
            var handler = new Mock <HttpMessageHandler>();
            var currencyConverterClientMock = new Mock <CurrencyConverterClient>(
                MockBehavior.Loose, null, handler.CreateClient(), null, null);

            currencyConverterClientMock
            .Setup(_ => _.RequestCurrencyConverter("CHF", "BTC"))
            .Returns(() => Task.FromResult(new ExchangeRateInfo
            {
                ExchangeRate = 0, RequestStatus = new RequestStatus(RequestStatusCode.Error)
            }))
            .Verifiable();
            var exchangeApiClientMock = new Mock <ExchangeRateApiClient>(
                MockBehavior.Loose, null, handler.CreateClient(), null, null);

            exchangeApiClientMock
            .Setup(_ => _.RequestExchangeRateApi("CHF", "BTC"))
            .Returns(() => Task.FromResult(new ExchangeRateInfo
            {
                ExchangeRate = (decimal)1.1, RequestStatus = new RequestStatus(RequestStatusCode.Ok)
            }))
            .Verifiable();

            var loggerMock = TestHelper.GetLoggerMock <ExchangeRateCacheStrategy>();

            var webRequestProvider = new ExchangeRateCacheStrategy(
                loggerMock.Object,
                currencyConverterClientMock.Object, exchangeApiClientMock.Object,
                TestHelper.GetFaceSettings(), TestHelper.GetMetricsMock().Object);

            // Act
            //
            var result = await webRequestProvider.GetExchangeRate("CHF", "BTC");


            // Assert
            //
            loggerMock.Verify(
                x => x.Log(
                    It.IsAny <LogLevel>(),
                    It.IsAny <EventId>(),
                    It.Is <It.IsAnyType>((o, t) => o.ToString().StartsWith("Fallback, object state ")),
                    It.IsAny <Exception>(),
                    (Func <It.IsAnyType, Exception, string>)It.IsAny <object>()),
                Times.Once);
        }
 public YAFaceController(
     ILogger <YAFaceController> logger, PostgresDataProvider postgresDataProvider, KafkaProvider kafkaProvider,
     ExchangeRateCacheStrategy exchangeRateCacheStrategy,
     VirtualearthClient virtualearthClient,
     DarkSkyClient darkSkyClient,
     OpenWeatherClient openWeatherClient,
     FaceSettings faceSettings)
 {
     _logger = logger;
     _postgresDataProvider      = postgresDataProvider;
     _kafkaProvider             = kafkaProvider;
     _exchangeRateCacheStrategy = exchangeRateCacheStrategy;
     _virtualearthClient        = virtualearthClient;
     _darkSkyClient             = darkSkyClient;
     _openWeatherClient         = openWeatherClient;
     _faceSettings = faceSettings;
 }
        public async void ExchangeRateWithErrorShouldFallbackAndReturnZeroForUnsupportedPair()
        {
            // Arrange
            //
            var handler = new Mock <HttpMessageHandler>();
            var currencyConverterClientMock = new Mock <CurrencyConverterClient>(
                MockBehavior.Loose, null, handler.CreateClient(), null, null);

            currencyConverterClientMock
            .Setup(_ => _.RequestCurrencyConverter("CHF", "BTC"))
            .Returns(() => Task.FromResult(new ExchangeRateInfo
            {
                ExchangeRate = 0, RequestStatus = new RequestStatus(RequestStatusCode.Error)
            }))
            .Verifiable();
            var exchangeApiClientMock = new Mock <ExchangeRateApiClient>(
                MockBehavior.Loose, null, handler.CreateClient(), null, null);

            exchangeApiClientMock
            .Setup(_ => _.RequestExchangeRateApi("CHF", "BTC"))
            .Returns(() => Task.FromResult(new ExchangeRateInfo
            {
                ExchangeRate = (decimal)1.1, RequestStatus = new RequestStatus(RequestStatusCode.Ok)
            }))
            .Verifiable();

            var webRequestProvider = new ExchangeRateCacheStrategy(
                TestHelper.GetLoggerMock <ExchangeRateCacheStrategy>().Object,
                currencyConverterClientMock.Object, exchangeApiClientMock.Object,
                TestHelper.GetFaceSettings(), TestHelper.GetMetricsMock().Object);

            // Act
            //
            var result = await webRequestProvider.GetExchangeRate("CHF", "BTC");


            // Assert
            //
            currencyConverterClientMock.Verify(_ => _.RequestCurrencyConverter(It.IsAny <string>(), It.IsAny <string>()), Times.Once);
            exchangeApiClientMock.Verify(_ => _.RequestExchangeRateApi(It.IsAny <string>(), It.IsAny <string>()), Times.Never);
            Assert.Equal(0, result.ExchangeRate);
            Assert.Equal(RequestStatusCode.HasNotBeenRequested, result.RequestStatus.StatusCode);
        }
Beispiel #5
0
        public async void After2FaultsCircuitBreakerShouldSendRequestsToFallback()
        {
            // Arrange
            //
            var config = new ConfigurationBuilder()
                         //.SetBasePath(AppContext.BaseDirectory)
                         .AddJsonFile("appsettings.json", false, true)
                         .AddJsonFile("appsettings.Development.json", false, true)
                         .Build();
            var settings = config.LoadVerifiedConfiguration <FaceSettings>();

            var mainUrl1     = settings.BuildCurrencyConverterUrl("USD", "RUB");
            var mainUrl2     = settings.BuildCurrencyConverterUrl("EUR", "PHP");
            var fallbackUrl1 = settings.BuildExchangeRateApiUrl("USD", "RUB");
            var fallbackUrl2 = settings.BuildExchangeRateApiUrl("EUR", "PHP");


            var handler = new Mock <HttpMessageHandler>();

            handler.SetupRequest(HttpMethod.Get, mainUrl1)
            .ReturnsResponse(HttpStatusCode.ServiceUnavailable)
            .Verifiable();
            handler.SetupRequest(HttpMethod.Get, mainUrl2)
            .ReturnsResponse(HttpStatusCode.ServiceUnavailable)
            .Verifiable();
            handler.SetupRequest(HttpMethod.Get, fallbackUrl1)
            .ReturnsResponse(HttpStatusCode.OK, "{\"rates\":{\"RUB\":50.9298531811},\"base\":\"USD\",\"date\":\"2020-03-30\"}")
            .Verifiable();
            handler.SetupRequest(HttpMethod.Get, fallbackUrl2)
            .ReturnsResponse(HttpStatusCode.OK, "{\"rates\":{\"PHP\":50.9298531811},\"base\":\"EUR\",\"date\":\"2020-03-30\"}")
            .Verifiable();

            var measureCounterMetrics = new Mock <IMeasureCounterMetrics>();

            var measureMetricMock = new Mock <IMeasureMetrics>();

            measureMetricMock.Setup(_ => _.Counter).Returns(measureCounterMetrics.Object);
            var metricsMock = new Mock <IMetrics>();

            metricsMock.Setup(_ => _.Measure).Returns(measureMetricMock.Object);

            var client = handler.CreateClient();

            IServiceCollection services = new ServiceCollection();



            var loggerCccMock = new Mock <ILogger <CurrencyConverterClient> >();
            var loggerErcMock = new Mock <ILogger <ExchangeRateApiClient> >();

            // var ccc = new CurrencyConverterClient(loggerCccMock.Object, handler.CreateClient(), settings, metricsMock.Object);
            // var erc = new ExchangeRateApiClient(loggerErcMock.Object, handler.CreateClient(), settings, metricsMock.Object);

            services.AddSingleton(settings);
            services.AddSingleton(loggerCccMock.Object);
            services.AddSingleton(loggerErcMock.Object);
            services.AddSingleton(metricsMock.Object);

            services.AddHttpClient <CurrencyConverterClient>()
            .AddRetryPolicyWithCb(2, TimeSpan.FromMinutes(10))
            .AddHttpMessageHandler(() => new StubDelegatingHandler(client));
            services.AddHttpClient <ExchangeRateApiClient>()
            .AddRetryPolicyWithCb(2, TimeSpan.FromMinutes(10))
            .AddHttpMessageHandler(() => new StubDelegatingHandler(client));



            var isp = services.BuildServiceProvider();

            var webRequestProvider = new ExchangeRateCacheStrategy(
                TestHelper.GetLoggerMock <ExchangeRateCacheStrategy>().Object,
                isp.GetRequiredService <CurrencyConverterClient>(), isp.GetRequiredService <ExchangeRateApiClient>(),
                settings, metricsMock.Object);


            // Act
            //
            var result1 = await webRequestProvider.GetExchangeRate("USD", "RUB");

            var result2 = await webRequestProvider.GetExchangeRate("EUR", "PHP");

            // Assert
            //
            handler.VerifyRequest(HttpMethod.Get, mainUrl1, Times.Exactly(2));
            handler.VerifyRequest(HttpMethod.Get, mainUrl2, Times.Exactly(0));
            handler.VerifyRequest(HttpMethod.Get, fallbackUrl1, Times.Exactly(1));
            handler.VerifyRequest(HttpMethod.Get, fallbackUrl2, Times.Exactly(1));
        }