Build the Calculation Engine
By the end of this lesson, you'll be able to:
- Write a LoanCalculationService with a monthly payment formula
- Apply a credit-score-based interest rate
- Write the first formal test class for this service, immediately
Prerequisites: "Design the Approval Logic"
The calculation service
public class LoanCalculationService {
public Decimal calculateInterestRate(Decimal creditScore) {
if (creditScore >= 700) {
return 6.5;
} else if (creditScore >= 600) {
return 9.0;
} else {
return 14.0;
}
}
public Decimal calculateMonthlyPayment(Decimal amount, Decimal annualRatePercent, Integer months) {
Decimal monthlyRate = (annualRatePercent / 100) / 12;
return (amount * monthlyRate) / (1 - Math.pow(1 + monthlyRate, -months));
}
}
calculateInterestRate is Module 6's if/else if/else chain; calculateMonthlyPayment implements the standard amortized-loan-payment formula, taking the principal, annual rate, and loan term in months.
Testing it immediately
@isTest
private class LoanCalculationServiceTest {
@isTest
static void highCreditScoreGetsLowestRate() {
LoanCalculationService service = new LoanCalculationService();
System.assertEquals(6.5, service.calculateInterestRate(750));
}
@isTest
static void midCreditScoreGetsMiddleRate() {
LoanCalculationService service = new LoanCalculationService();
System.assertEquals(9.0, service.calculateInterestRate(650));
}
@isTest
static void lowCreditScoreGetsHighestRate() {
LoanCalculationService service = new LoanCalculationService();
System.assertEquals(14.0, service.calculateInterestRate(550));
}
}
Three test methods, one per branch of the if/else if/else chain — this is Module 31's Lesson 2 habit ("one test method, one scenario") applied the moment the logic is written, not saved for a separate lesson afterward.
Testing the boundary values specifically
@isTest
static void creditScoreOf700IsTheLowestQualifyingForBestRate() {
LoanCalculationService service = new LoanCalculationService();
System.assertEquals(6.5, service.calculateInterestRate(700));
}
@isTest
static void creditScoreOf699JustMissesTheBestRate() {
LoanCalculationService service = new LoanCalculationService();
System.assertEquals(9.0, service.calculateInterestRate(699));
}
Testing exactly 700 and 699 — the boundary between two branches — is where off-by-one bugs (> instead of >=, from Module 4) actually hide. This is Module 31's "assertions that actually tell you something" lesson, applied specifically to boundary conditions.
Exercise
Write a test confirming calculateInterestRate(600) returns 9.0 (the boundary between the middle and lowest tiers).
Show hint
Test the exact boundary value, not just a value comfortably inside the range.
Build the Calculation Engine Quiz
My Notes
Log in to keep private notes on this lesson.
Questions about this lesson
No questions yet — be the first to ask.
Log in to ask a question about this lesson.
Summary
This lesson builds the calculation logic and its test class together — the standard shape of every lesson going forward in this module.