Beispiel #1
0
        public async Task GetSingleQuoteData_ShouldReturnSingleQuoteQueryResultWithoutError_WhenSuccessful()
        {
            var singleQuoteData = new SingleQuoteData(
                symbolId: 1,
                ticker: "MSFT",
                high: 1,
                low: 2,
                open: 3,
                previousClose: 4,
                volume: 5,
                change: 6,
                price: 7,
                changePercent: 0.9m,
                lastUpdated: DateTime.UtcNow,
                lastTradingDay: DateTime.UtcNow
                );

            var client = new AlphaVantageClient(_mockHttpFactory.Object, _mockAlphaVantageOptionsAccessor.Object, _mockParserFactory.Object, _mockLogger.Object);

            SetupMockHttpClient("mockData", HttpStatusCode.OK);
            _singleQuoteDataCsvParser.Setup(x => x.ParseJson(-1, It.IsAny <string>())).Returns(singleQuoteData);

            var query       = new SingleQuoteQuery(-1);
            var queryResult = await client.GetSingleQuoteData(query, "MSFT", "NASDAQ");

            Assert.False(queryResult.HasError);
            Assert.Equal("MSFT", queryResult.Data.Ticker);
            Assert.Equal(singleQuoteData.LastUpdated, queryResult.Data.LastUpdated);
        }
 public async Task UpsertSingleQuoteData_ShouldThrowException_WhenSavingFailed()
 {
     _stockDataRepository.Setup(s => s.UpsertSingleQuoteData(It.IsAny <UpsertSingleQuoteData>())).Returns(Task.FromResult(false));
     var query       = new SingleQuoteQuery(1);
     var queryResult = new SingleQuoteQueryResult("MSFT", _singleQuoteData);
     await Assert.ThrowsAsync <ArgumentException>(async() => await _service.UpsertSingleQuoteData(query, queryResult));
 }
Beispiel #3
0
        public async Task GetSingleQuoteData_ShouldReturnQueryResultWithError_WhenErrorSendingRequestWithHttpClient()
        {
            var client = new AlphaVantageClient(_mockHttpFactory.Object, _mockAlphaVantageOptionsAccessor.Object, _mockParserFactory.Object, _mockLogger.Object);

            _mockHttpFactory = new Mock <IHttpClientFactory>();

            var handlerMock = new Mock <HttpMessageHandler>(MockBehavior.Strict);

            handlerMock
            .Protected()
            .Setup <Task <HttpResponseMessage> >(
                "SendAsync",
                ItExpr.IsAny <HttpRequestMessage>(),
                ItExpr.IsAny <CancellationToken>()
                )
            .Throws <Exception>();

            var httpClient = new HttpClient(handlerMock.Object);

            _mockHttpFactory.Setup(x => x.CreateClient(It.IsAny <string>())).Returns(httpClient);

            var query       = new SingleQuoteQuery(-1);
            var queryResult = await client.GetSingleQuoteData(query, "MSFT", "NASDAQ");

            Assert.True(queryResult.HasError);
            Assert.NotNull(queryResult.ErrorMessage);
        }
Beispiel #4
0
        public void GetSubscriptionInfos_ReturnsSubscriberCountEqualsTimesAdded_WhenMultipleQueries()
        {
            var querySubscription = new QuerySubscriptions();

            var queryCount = 2;
            var query      = new SingleQuoteQuery(1);

            var queryCount2 = 3;
            var query2      = new SingleQuoteQuery(2);

            for (var i = 0; i < queryCount; i++)
            {
                querySubscription.AddSubscriber(query);
            }

            for (var i = 0; i < queryCount2; i++)
            {
                querySubscription.AddSubscriber(query2);
            }

            var querySubscriptionInfos = querySubscription.GetSubscriptionInfos();

            Assert.Equal(2, querySubscriptionInfos.Count());

            var subcribedQuery  = querySubscriptionInfos.First(x => x.Query == query);
            var subcribedQuery2 = querySubscriptionInfos.First(x => x.Query == query2);

            Assert.Equal(queryCount, subcribedQuery.SubscriberCount);
            Assert.Equal(queryCount2, subcribedQuery2.SubscriberCount);
        }
Beispiel #5
0
        /// <summary>
        /// Saves the single quote query result or updates it if it already exists.
        /// </summary>
        /// <param name="query"><see cref="SingleQuoteQuery"/> to upsert data for.</param>
        /// <param name="queryResult"><see cref="SingleQuoteQueryResult"/> stock data results to save.</param>
        /// <remarks>
        /// Will update the database and then <see cref="SingleQuoteCache"/> if it was successful.
        /// Error results will be ignored.
        /// </remarks>
        public async Task UpsertSingleQuoteData(SingleQuoteQuery query, SingleQuoteQueryResult queryResult)
        {
            if (queryResult.HasError)
            {
                return;
            }

            _logger.LogTrace("Query SymbolId {id} added to cache", query.SymbolId);

            const int primaryKeyViolationCode = 2627;

            try
            {
                bool successfulSave = await _stockDataRepository.UpsertSingleQuoteData(new UpsertSingleQuoteData(query.SymbolId, queryResult.Data));

                _logger.LogTrace("Query SymbolId {id} saved to database", query.SymbolId);

                if (!successfulSave)
                {
                    throw new ArgumentException($"query for symbolId {query.SymbolId} was not able to be updated");
                }
            }
            catch (SqlException ex) when(ex.ErrorCode == primaryKeyViolationCode)
            {
                _logger.LogError("Query SymbolId {id} was duplicate insert in database", query.SymbolId);

                // Ignore the error since it means a race condition where we tried insert twice.
                // But that's fine since the stock data is unlikely to be different if it's that close in time.
                // This is more performant than adding locks as this case should be very exceptional.
            }

            // Only insert into cache if it successfully saved into database.
            _singleQuoteCache.Upsert(query.SymbolId, queryResult);
        }
Beispiel #6
0
        public void GetSubscriberCount_ShouldReturnZero_WhenQueryNotFound()
        {
            var querySubscription = new QuerySubscriptions();

            var query = new SingleQuoteQuery(1);

            long subscriberCount = querySubscription.GetSubscriberCount(query);

            Assert.Equal(0, subscriberCount);
        }
        public async Task UpsertSingleQuoteData_ShouldNotUpsertSingleQuoteData_WhenQueryResultHasError()
        {
            _stockDataRepository.Setup(s => s.UpsertSingleQuoteData(It.IsAny <UpsertSingleQuoteData>())).Returns(Task.FromResult(true));
            var query       = new SingleQuoteQuery(1);
            var queryResult = new SingleQuoteQueryResult("error");
            await _service.UpsertSingleQuoteData(query, queryResult);

            _stockDataRepository.Verify(s => s.UpsertSingleQuoteData(It.IsAny <UpsertSingleQuoteData>()), Times.Never);
            Assert.False(_cache.TryGet(query.SymbolId, out SingleQuoteQueryResult cachedResult));
        }
Beispiel #8
0
        public async Task GetSingleQuoteData_ShouldReturnQueryResultWithError_WhenHttpRequestNotOK()
        {
            var client = new AlphaVantageClient(_mockHttpFactory.Object, _mockAlphaVantageOptionsAccessor.Object, _mockParserFactory.Object, _mockLogger.Object);

            SetupMockHttpClient("", HttpStatusCode.Unauthorized);

            var query       = new SingleQuoteQuery(-1);
            var queryResult = await client.GetSingleQuoteData(query, "MSFT", "NASDAQ");

            Assert.True(queryResult.HasError);
        }
Beispiel #9
0
        public async Task GetSingleQuote_ShouldReturnErrorWhenUnknownSymbol()
        {
            var query              = new SingleQuoteQuery(-1);
            var ticker             = "AB1234567890";
            var alphaVantageClient = new AlphaVantageClient(_mockHttpFactory, _mockAlphaVantageOptionsAccessor.Object, _parserFactory, _mockLogger.Object);

            SingleQuoteQueryResult singleQuoteResult = await alphaVantageClient.GetSingleQuoteData(query, ticker, "NYSE");

            Assert.True(singleQuoteResult.HasError);
            Assert.False(string.IsNullOrEmpty(singleQuoteResult.ErrorMessage));
        }
        public async Task GetSingleQuoteData_ShouldGetValueFromCache()
        {
            var query       = new SingleQuoteQuery(1);
            var queryResult = new SingleQuoteQueryResult("MSFT", _singleQuoteData);

            _cache.Upsert(query.SymbolId, queryResult);

            StockSingleQuoteDataDTO data = await _service.GetSingleQuoteData(query.SymbolId);

            Assert.Equal(queryResult.Data, data.Data);
            _stockDataRepository.Verify(s => s.GetSingleQuoteData(It.IsAny <int>()), Times.Never);
        }
Beispiel #11
0
        public void GetSubscriptionInfos_ReturnsZeroSubscriberCount_WhenQueryCleared()
        {
            var querySubscription = new QuerySubscriptions();

            var query = new SingleQuoteQuery(1);

            querySubscription.AddSubscriber(query);
            querySubscription.ClearQuery(query);
            var querySubscriptionInfos = querySubscription.GetSubscriptionInfos();

            Assert.Empty(querySubscriptionInfos);
        }
        public async Task UpsertSingleQuoteData_ShouldUpsertSingleQuoteDataAndSaveIntoCache()
        {
            _stockDataRepository.Setup(s => s.UpsertSingleQuoteData(It.IsAny <UpsertSingleQuoteData>())).Returns(Task.FromResult(true));
            var query       = new SingleQuoteQuery(1);
            var queryResult = new SingleQuoteQueryResult("MSFT", _singleQuoteData);
            await _service.UpsertSingleQuoteData(query, queryResult);

            _stockDataRepository.Verify(s => s.UpsertSingleQuoteData(It.Is <UpsertSingleQuoteData>(u => u.SymbolId == query.SymbolId)));
            _cache.TryGet(query.SymbolId, out SingleQuoteQueryResult cachedResult);

            Assert.Equal(queryResult, cachedResult);
        }
Beispiel #13
0
        public void GetSubscriberCount_ShouldReturnSubcriberCount_ForQuery()
        {
            var querySubscription = new QuerySubscriptions();

            var query = new SingleQuoteQuery(1);

            querySubscription.AddSubscriber(query);
            querySubscription.AddSubscriber(query);

            long subscriberCount = querySubscription.GetSubscriberCount(query);

            Assert.Equal(2, subscriberCount);
        }
Beispiel #14
0
        public async Task GetSingleQuoteData_ShouldReturnQueryResultWithError_WhenParsingError()
        {
            var query  = new SingleQuoteQuery(-1);
            var client = new AlphaVantageClient(_mockHttpFactory.Object, _mockAlphaVantageOptionsAccessor.Object, _mockParserFactory.Object, _mockLogger.Object);

            SetupMockHttpClient("", HttpStatusCode.OK);
            _singleQuoteDataCsvParser.Setup(x => x.ParseJson(It.IsAny <int>(), It.IsAny <string>())).Throws(new Exception());

            var queryResult = await client.GetSingleQuoteData(query, "MSFT", "NASDAQ");

            Assert.True(queryResult.HasError);
            Assert.NotNull(queryResult.ErrorMessage);
        }
        public async Task GetSingleQuoteData_ShouldGetValueFromDBAndSaveToCache_WhenNotInCache()
        {
            var query       = new SingleQuoteQuery(1);
            var queryResult = new SingleQuoteQueryResult("MSFT", _singleQuoteData);

            _stockDataRepository.Setup(s => s.GetSingleQuoteData(It.IsAny <int>())).Returns(Task.FromResult(_singleQuoteData));

            StockSingleQuoteDataDTO data = await _service.GetSingleQuoteData(query.SymbolId);

            Assert.Equal(queryResult.Data, data.Data);
            _stockDataRepository.Verify(s => s.GetSingleQuoteData(It.IsAny <int>()), Times.Once);
            _cache.TryGet(query.SymbolId, out SingleQuoteQueryResult cachedResult);

            Assert.Equal(queryResult.Data, cachedResult.Data);
        }
Beispiel #16
0
        public void GetSubscriptionInfos_ReturnsSubscriberCountEqualTimesAdded(int timesAdded)
        {
            var querySubscription = new QuerySubscriptions();

            var query = new SingleQuoteQuery(1);

            for (var i = 0; i < timesAdded; i++)
            {
                querySubscription.AddSubscriber(query);
            }

            var querySubscriptionInfos = querySubscription.GetSubscriptionInfos();

            Assert.Single(querySubscriptionInfos);
            Assert.Equal(timesAdded, querySubscriptionInfos.Single().SubscriberCount);
            Assert.Equal(query, querySubscriptionInfos.Single().Query);
        }
Beispiel #17
0
 public SingleQuoteContext(
     IStockClient stockClient,
     SingleQuoteCache queryResultCache,
     ISymbolRepository symbolRepository,
     IStockDataService stockDataService,
     IStockNotificationCenter notificationCenter,
     SingleQuoteQuery query,
     ILogger <SingleQuoteContext> logger)
 {
     _stockClient        = stockClient;
     _queryResultCache   = queryResultCache;
     _symbolRepository   = symbolRepository;
     _stockDataService   = stockDataService;
     _notificationCenter = notificationCenter;
     _query  = query;
     _logger = logger;
 }
Beispiel #18
0
        public void GetSubscriptionInfos_SubscriberCountNeverLessThanZero_WhenSubscribersRemoved()
        {
            var querySubscription = new QuerySubscriptions();

            var query = new SingleQuoteQuery(1);

            querySubscription.AddSubscriber(query);

            querySubscription.RemoveSubscriber(query);
            querySubscription.RemoveSubscriber(query);
            querySubscription.RemoveSubscriber(query);

            var querySubscriptionInfos = querySubscription.GetSubscriptionInfos();

            Assert.Single(querySubscriptionInfos);
            Assert.Equal(0, querySubscriptionInfos.Single().SubscriberCount);
            Assert.Equal(query, querySubscriptionInfos.Single().Query);
        }
Beispiel #19
0
        public async Task GetSingleQuote_ShouldReturnSingleQuoteStockData()
        {
            var query              = new SingleQuoteQuery(-1);
            var ticker             = "MSFT";
            var alphaVantageClient = new AlphaVantageClient(_mockHttpFactory, _mockAlphaVantageOptionsAccessor.Object, _parserFactory, _mockLogger.Object);

            SingleQuoteQueryResult singleQuoteResult = await alphaVantageClient.GetSingleQuoteData(query, ticker, "NASDAQ");

            Assert.False(singleQuoteResult.HasError);

            Assert.True(singleQuoteResult.Data.Low >= 0);
            Assert.True(singleQuoteResult.Data.High >= 0);
            Assert.True(singleQuoteResult.Data.Open >= 0);
            Assert.True(singleQuoteResult.Data.Volume >= 0);
            Assert.True(singleQuoteResult.Data.Price >= 0);
            Assert.True(singleQuoteResult.Data.PreviousClose >= 0);
            Assert.True(singleQuoteResult.Data.LastUpdated > new DateTime());
            Assert.True(singleQuoteResult.Data.LastTradingDay > new DateTime());
            Assert.Equal(ticker, singleQuoteResult.Data.Ticker);
        }
Beispiel #20
0
        public void GetSubscriptionInfos_ReturnsSubscriberCountEqualTimesAddedAndSubtracted_WhenSingleQuery(int timesAdded, int timesRemoved)
        {
            var querySubscription = new QuerySubscriptions();

            var query = new SingleQuoteQuery(1);

            for (var i = 0; i < timesAdded; i++)
            {
                querySubscription.AddSubscriber(query);
            }

            for (var i = 0; i < timesRemoved; i++)
            {
                querySubscription.RemoveSubscriber(query);
            }

            var querySubscriptionInfos = querySubscription.GetSubscriptionInfos();
            var expectedCount          = Math.Abs(timesAdded - timesRemoved);

            Assert.Single(querySubscriptionInfos);
            Assert.Equal(expectedCount, querySubscriptionInfos.Single().SubscriberCount);
            Assert.Equal(query, querySubscriptionInfos.Single().Query);
        }
Beispiel #21
0
        public void AddSubscriberToSingleQuote(int symbolId)
        {
            var query = new SingleQuoteQuery(symbolId);

            _querySubscriptions.AddSubscriber(query);
        }
Beispiel #22
0
 public SingleQuoteContext GenerateSingleQuoteContext(SingleQuoteQuery query)
 {
     return(_singleQuoteFactory(query));
 }