public async Task Add_Stake_WithCorrectAmountOfCurrency()
        {
            var contextOptions = new DbContextOptionsBuilder <CasinoContext>()
                                 .UseInMemoryDatabase(databaseName: "Add_Stake_WithCorrectAmountOfCurrency")
                                 .Options;

            var currencyServiceMock = new Mock <ICurrencyRateApiService>();

            var baseCurrency  = "USD";
            var currency      = 1.50;
            var serviceReturn = new ConcurrentDictionary <string, double>();

            serviceReturn.TryAdd(baseCurrency, currency);
            currencyServiceMock.Setup(s => s.GetRatesAsync()).Returns(Task.FromResult(serviceReturn));

            string userId = "userId";
            double amountInUserCurrency = 50;
            string description          = "1234567890";

            var user = new User()
            {
                Id     = userId,
                Wallet = new Wallet()
                {
                    Id       = "walledId",
                    Currency = new Currency()
                    {
                        Id   = 1,
                        Name = baseCurrency
                    },
                    DisplayBalance    = 750,
                    NormalisedBalance = 500
                }
            };

            using (var context = new CasinoContext(contextOptions))
            {
                context.Users.Add(user);
                await context.SaveChangesAsync();

                var transactionService = new TransactionService(context, currencyServiceMock.Object);

                var savedTransaction = await transactionService.AddStakeTransaction(userId, amountInUserCurrency, description);

                var originalAmount    = savedTransaction.OriginalAmount;
                var normalisedAmount  = savedTransaction.NormalisedAmount;
                var userAmount        = context.Users.Find(userId).Wallet.NormalisedBalance;
                var userDisplayAmount = context.Users.Find(userId).Wallet.DisplayBalance;
                var winTransaction    = savedTransaction.TransactionTypeId;

                Assert.AreEqual(amountInUserCurrency, originalAmount);
                Assert.AreEqual(amountInUserCurrency / currency, normalisedAmount);
                Assert.AreEqual(500 - amountInUserCurrency / currency, userAmount);
                Assert.AreEqual(750 - amountInUserCurrency, userDisplayAmount);
                Assert.IsTrue(winTransaction == 2);
            }
        }
        public async Task ThrowArgumentOutOfRangeException_WhenAmountOfUserCurrencyIsSmallerThenZero()
        {
            var casinoContextMock   = new Mock <CasinoContext>();
            var currencyServiceMock = new Mock <ICurrencyRateApiService>();

            string userId = "userId";
            double amountInUserCurrency = -1;
            string description          = "1234567890";

            var transactionService = new TransactionService(casinoContextMock.Object, currencyServiceMock.Object);

            await Assert.ThrowsExceptionAsync <ArgumentOutOfRangeException>(() => transactionService.AddStakeTransaction(userId, amountInUserCurrency, description));
        }
        public async Task ThrowArgumentOutOfRangeException_WhenDesctiptionIsLongerThen100()
        {
            var casinoContextMock   = new Mock <CasinoContext>();
            var currencyServiceMock = new Mock <ICurrencyRateApiService>();

            string userId = "userId";
            double amountInUserCurrency = 50;
            string description          = new string('-', 101);

            var transactionService = new TransactionService(casinoContextMock.Object, currencyServiceMock.Object);

            await Assert.ThrowsExceptionAsync <ArgumentOutOfRangeException>(() => transactionService.AddStakeTransaction(userId, amountInUserCurrency, description));
        }
        public async Task ThrowArgumentNullException_WhenUserIdIsNull()
        {
            var casinoContextMock   = new Mock <CasinoContext>();
            var currencyServiceMock = new Mock <ICurrencyRateApiService>();

            string userId = null;
            double amountInUserCurrency = 50;
            string description          = "1234567890";

            var transactionService = new TransactionService(casinoContextMock.Object, currencyServiceMock.Object);

            await Assert.ThrowsExceptionAsync <ArgumentNullException>(() => transactionService.AddStakeTransaction(userId, amountInUserCurrency, description));
        }
        public async Task ThrowWhenInsufficientFunds()
        {
            var contextOptions = new DbContextOptionsBuilder <CasinoContext>()
                                 .UseInMemoryDatabase(databaseName: "ThrowWhenInsufficientFunds")
                                 .Options;

            var currencyServiceMock = new Mock <ICurrencyRateApiService>();

            var baseCurrency  = "USD";
            var currency      = 1.50;
            var serviceReturn = new ConcurrentDictionary <string, double>();

            serviceReturn.TryAdd(baseCurrency, currency);
            currencyServiceMock.Setup(s => s.GetRatesAsync()).Returns(Task.FromResult(serviceReturn));

            string userId = "userId";
            double amountInUserCurrency = 50;
            string description          = "1234567890";

            var user = new User()
            {
                Id     = userId,
                Wallet = new Wallet()
                {
                    Id       = "walledId",
                    Currency = new Currency()
                    {
                        Id   = 1,
                        Name = baseCurrency
                    },
                }
            };

            using (var context = new CasinoContext(contextOptions))
            {
                context.Users.Add(user);
                await context.SaveChangesAsync();

                var transactionService = new TransactionService(context, currencyServiceMock.Object);

                await Assert.ThrowsExceptionAsync <InsufficientFundsException>(
                    () => transactionService.AddStakeTransaction(userId, amountInUserCurrency, description));
            }
        }
        public async Task ThrowEntityNotFoundException_WhenUserWithGivenIdIsNotFoundInDatabase()
        {
            var contextOptions = new DbContextOptionsBuilder <CasinoContext>()
                                 .UseInMemoryDatabase(databaseName: "LossThrowEntityNotFoundException_WhenUserWithGivenIdIsNotFoundInDatabase")
                                 .Options;

            var currencyServiceMock = new Mock <ICurrencyRateApiService>();

            string userId = "userId";
            double amountInUserCurrency = 50.05;
            string description          = "1234567890";

            using (var context = new CasinoContext(contextOptions))
            {
                var transactionService = new TransactionService(context, currencyServiceMock.Object);

                await Assert.ThrowsExceptionAsync <EntityNotFoundException>(() => transactionService.AddStakeTransaction(userId, amountInUserCurrency, description));
            }
        }