public void Withdraw_InsufficientFunds_Exception() { // setup entities var account = ObjectBuilder.BuildAccount(null); account.Balance = 50; // setup repo var mockRepo = new Mock <IAccountRepository>(MockBehavior.Strict); //mockRepo.Setup(r => r.GetByAccountNumber(account.AccountNumber)).Returns(account); mockRepo.Setup(r => r.GetTransactionsForAccountOnDate(It.IsAny <int>(), It.IsAny <DateTimeOffset>())).Returns(new List <Transaction>()); mockRepo.Setup(r => r.AddTransaction(It.IsAny <Transaction>())).Verifiable(); mockRepo.Setup(r => r.UpdateAccount(It.IsAny <Account>())).Verifiable(); var accountService = new AccountService(mockRepo.Object); // attempt to withdraw amount, assert that exception is thrown accountService.Invoking(s => { // tell fluent assertions to watch events using (var subscriptionService = s.SubscriptionService.Monitor()) { s.Withdraw(account, 60); // assert that no event was raised (if for some reason we get this far) subscriptionService.Should().NotRaise("AccountChangedEvent", "because this illegal action should not have caused any account change"); } }).Should().ThrowExactly <InsufficientFundsException>(); // check no changes made it to the repository mockRepo.Verify(r => r.AddTransaction(It.IsAny <Transaction>()), Times.Never, "The repository method add transaction shouldn't have been invoked as the illegal action shouldn't have been a resultant transaction"); mockRepo.Verify(r => r.UpdateAccount(It.IsAny <Account>()), Times.Never, "The repository method update account shouldn't have been invoked as the illegal action shouldn't have caused any account change"); }
public void Withdraw_NotMultipleOfTen_Exception() { // setup entities var account = ObjectBuilder.BuildAccount(null); account.Balance = 1000; // setup repo var mockRepo = new Mock <IAccountRepository>(MockBehavior.Strict); mockRepo.Setup(r => r.UpdateAccount(It.IsAny <Account>())).Verifiable(); mockRepo.Setup(r => r.AddTransaction(It.IsAny <Transaction>())).Verifiable(); var accountService = new AccountService(mockRepo.Object); accountService.Invoking(s => { using (var subscriptionService = s.SubscriptionService.Monitor()) { s.Withdraw(account, 12); subscriptionService.Should().NotRaise("AccountChangedEvent", "because the illegal action should not cause an update"); } }).Should().ThrowExactly <AmountException>("because we attempted to withdraw 12 from an account which is not a multiple of 10"); // check no changes were made to the repository mockRepo.Verify(r => r.UpdateAccount(It.IsAny <Account>()), Times.Never, "The repository method update account shouldn't have been invoked as the action was illegal"); mockRepo.Verify(r => r.AddTransaction(It.IsAny <Transaction>()), Times.Never, "The repository method add transaction shouldn't have been invoked as the action was illegal"); }
public void Withdraw_Normal_Success() { // setup entities var account = ObjectBuilder.BuildAccount(null); account.Balance = 60; var date = DateTimeOffset.UtcNow.Date; var transactions = new List <Transaction>() { ObjectBuilder.BuildTransaction(account.Id, 10, date.AddHours(5)) }; // setup repo var mockRepo = new Mock <IAccountRepository>(MockBehavior.Strict); mockRepo.Setup(r => r.GetTransactionsForAccountOnDate(account.Id, date)).Returns(transactions); mockRepo.Setup(r => r.AddTransaction(It.IsAny <Transaction>())).Verifiable(); // setup callback to catch the updated account Account caughtAccount = null; mockRepo.Setup(r => r.UpdateAccount(It.IsAny <Account>())).Callback <Account>(a => { caughtAccount = a; }).Verifiable(); Transaction returnedTransaction; var accountService = new AccountService(mockRepo.Object); // tell fluent assertions to check for event using (var subscriptionService = accountService.SubscriptionService.Monitor()) { // perform the operation returnedTransaction = accountService.Withdraw(account, 50); // check the event was fired subscriptionService.Should().Raise("AccountChangedEvent", "because this event should be thrown when withdrawing from an account"); } // assert transaction was created successfully mockRepo.Verify(r => r.AddTransaction(It.IsAny <Transaction>()), Times.Once, "Repository add transaction method should've run once"); returnedTransaction.Should().NotBeNull("because repository add transaction method has been invoked"); returnedTransaction.AccountId.Should().Be(account.Id, "because this is the id of the account the withdrawal was performed on"); returnedTransaction.Amount.Should().Be(-50, "because this is the amount that was withdrawn from the account"); returnedTransaction.Time.Should().BeCloseTo(DateTimeOffset.UtcNow, 1000, "because the transaction should have the current time"); // assert account was updated correctly mockRepo.Verify(r => r.UpdateAccount(It.IsAny <Account>()), Times.Once, "Repository update account method should've run once"); caughtAccount.Should().NotBeNull("because repository update account method has been invoked"); caughtAccount.Id.Should().Be(account.Id, "because this is the id of the account we updated"); caughtAccount.Balance.Should().Be(10, "because the account had 60, then had 50 withdrawn, leaving 10"); }
public void Withdraw_ExceedLimit_Exception() { // setup entities var account = ObjectBuilder.BuildAccount(null); account.Balance = 1000; var date = DateTimeOffset.UtcNow.Date; var transactions = new List <Transaction>() { ObjectBuilder.BuildTransaction(account.Id, -50, date.AddHours(5)), ObjectBuilder.BuildTransaction(account.Id, -100, date.AddHours(6)), ObjectBuilder.BuildTransaction(account.Id, -25, date.AddHours(8)), ObjectBuilder.BuildTransaction(account.Id, -25, date.AddHours(8)), ObjectBuilder.BuildTransaction(account.Id, -50, date.AddHours(9)) }; // setup repo var mockRepo = new Mock <IAccountRepository>(MockBehavior.Strict); mockRepo.Setup(r => r.GetTransactionsForAccountOnDate(account.Id, It.Is <DateTimeOffset>(x => x.Date == date))).Returns(transactions); mockRepo.Setup(r => r.UpdateAccount(It.IsAny <Account>())).Verifiable(); mockRepo.Setup(r => r.AddTransaction(It.IsAny <Transaction>())).Verifiable(); var accountService = new AccountService(mockRepo.Object); // attempt to withdraw amount, assert that exception is thrown accountService.Invoking(s => { // tell fluent assertions to watch events using (var subscriptionService = s.SubscriptionService.Monitor()) { s.Withdraw(account, 10); // assert that no event was raised (if for some reason we get this far) subscriptionService.Should().NotRaise("AccountChangedEvent", "because the illegal action should not cause an update"); } }).Should().ThrowExactly <WithdrawLimitException>("because the account has hit it's withdrawal limit for the day"); // check no changes made it to the repository mockRepo.Verify(r => r.UpdateAccount(It.IsAny <Account>()), Times.Never, "The repository method update account shouldn't have run as the action was illegal"); mockRepo.Verify(r => r.AddTransaction(It.IsAny <Transaction>()), Times.Never, "The repository method add transaction shouldn't have been invoked as the action was illegal"); }