A hands-on Test-Driven Development (TDD) exercise for practicing JUnit 5 and Mockito with a simple calculator application.
src/
├── main/java/com/codebar/calculator/
│ ├── Calculator.java # Basic calculator operations
│ └── CalculatorService.java # Service layer using Calculator
└── test/java/com/codebar/calculator/
├── CalculatorTest.java # Unit tests for Calculator
└── CalculatorServiceTest.java # Integration tests with Mockito
- Java 17 or higher
- Maven 3.6+
mvn clean compilemvn testmvn test jacoco:reportFollow the Red-Green-Refactor cycle:
- Write a failing test first
- Run the test and see it fail
- Ensure the failure is for the right reason
- Write the minimum code to make the test pass
- Run the test and see it pass
- Don't worry about code quality yet
- Improve the code while keeping tests green
- Remove duplication
- Improve naming and structure
- Run tests frequently to ensure nothing breaks
Implement and test basic calculator operations:
add(int a, int b)- Add two numberssubtract(int a, int b)- Subtract two numbersmultiply(int a, int b)- Multiply two numbersdivide(int a, int b)- Divide two numbers
Test cases to consider:
- Positive numbers
- Negative numbers
- Zero
- Edge cases (division by zero, overflow, etc.)
Practice Mockito by testing the CalculatorService:
calculateTotal(int... numbers)- Sum all numberscalculateAverage(int... numbers)- Calculate averagemultiplyAll(int... numbers)- Multiply all numbers
Learn to:
- Mock dependencies using
@Mock - Inject mocks using
@InjectMocks - Stub method behavior with
when().thenReturn() - Verify method calls with
verify() - Test interaction between objects
@Test- Marks a test method@BeforeEach- Runs before each test@DisplayName- Custom test name for reports@ExtendWith(MockitoExtension.class)- Enables Mockito
@Mock- Creates a mock instance@InjectMocks- Creates instance and injects mockswhen().thenReturn()- Stubs method behaviorverify()- Verifies method was calledtimes()- Specifies number of invocations
assertEquals(expected, actual)
assertTrue(condition)
assertFalse(condition)
assertThrows(Exception.class, () -> code)
assertNotNull(object)- Write one test at a time
- Start with the simplest test case
- Make small incremental changes
- Run tests frequently
- Refactor only when tests are green
- Test behavior, not implementation
- Use descriptive test names
This is a practice project for educational purposes.