public void ShouldInvokeLoanCalculatorAndReturnResult()
        {
            var input = new LoanParameters { Amount = 1, Years = 1 };
            var mockResponse = new PaymentPlan(new List<PaymentMonth>());
            _calculatorMock.Setup(it => it.CalculateLoan(input))
                .Returns(mockResponse)
                .Verifiable("Should call LoanCalculator with expected input");

            var result = _controller.Calculate(input);

            _calculatorMock.Verify();
            Assert.AreSame(mockResponse, result);
        }
 public PaymentPlan Calculate(LoanParameters parameters)
 {
     //TODO: Extract validation and error handling to generic functionality
     try {
         Validate(parameters);
         return _calculator.CalculateLoan(parameters);
     }
     catch (Exception ae)
     {
         var response = Request.CreateErrorResponse(HttpStatusCode.BadRequest, ae.Message);
         throw new HttpResponseException(response);
          
     }
 }
 private static void Validate(LoanParameters loanParameters)
 {
     if (loanParameters == null)
     {
         throw new ArgumentNullException(nameof(loanParameters));
     }
     if (loanParameters.Years <= 0)
     {
         throw new ZeroOrNegativeYearsException(nameof(loanParameters.Years), loanParameters.Years);
     }
     if (loanParameters.Amount < 0)
     {
         throw new NegativeAmountException(nameof(loanParameters.Amount), loanParameters.Amount);
     }
 }
        public PaymentPlan CalculateLoan(LoanParameters loanParameters)
        {
            var loan = new HousingLoan(loanParameters);
            var paymentScheme = new SeriesPaymentScheme();
            var months = new List<PaymentMonth>();
            
            for (int monthNumber = 1; monthNumber <= loan.NumberOfMonths; monthNumber++)
            {
                decimal monthlyPrincipal = paymentScheme.NextMonthlyPrincipal(loan);
                var monthlyInterest = paymentScheme.NextMonthlyInterest(loan);
                var monthlyTotal = monthlyPrincipal + monthlyInterest;
                loan.Remaining -= monthlyPrincipal; //TODO: This doesn't smell right, should be immutable or just a local variable?
                
                months.Add(new PaymentMonth(monthNumber, monthlyPrincipal, monthlyInterest, monthlyTotal, loan.Remaining));
            }

            var result = new PaymentPlan(months);

            return result;
        }
 internal LoanStub(LoanParameters loanParameters) : base(loanParameters) { }
 protected AbstractLoan(LoanParameters loanParameters)
 {
     Remaining = loanParameters.Amount;
     LoanAmount = loanParameters.Amount;
     NumberOfMonths = loanParameters.Years * 12;
 }