JUnit
Unit tests with JUnit
A popular open-source testing framework for Java
Reminder: Unit Testing
- Testing individual units of code
- Verifying that each unit behaves as expected
- Essential for detecting bugs
- Avoid regressions (Prevents new changes from breaking existing code)
Test classes
- One-to-One Relationship
- Each class you write should have a corresponding test class
- Book.java ➡️ BookTest.java
- placed in the same package as the class being tested
- but in the
src/test/java
directory
Example
Class Fraction
Fraction.java
public class Fraction {
@Getter private int numerator;
@Getter private int denominator;
public Fraction(int numerator, int denominator) {
if (denominator == 0)
throw new IllegalArgumentException("Denominator cannot be zero.");
this.numerator = numerator;
this.denominator = denominator;
}
public Fraction invert() {
if (numerator == 0)
throw new ArithmeticException("Cannot invert a fraction with a zero numerator.");
return new Fraction(denominator, numerator);
}
}
- @Getter : using Lombok
- Create method getAttribute()
Test class
FractionTest.java
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class FractionTest {
@Test
void testInvertValid() {
// GIVEN
= new Fraction(2, 3);
Fraction fraction
// WHEN
= fraction.invert();
Fraction inverted
// THEN
assertEquals(3, inverted.getNumerator());
assertEquals(2, inverted.getDenominator());
}
@Test
void testInvertZeroNumerator() {
= new Fraction(0, 5);
Fraction fraction assertThrows(ArithmeticException.class, fraction::invert);
}
}
Assertions
- assertEquals(expected, actual)
- assertTrue(condition) / assertFalse(condition)
- assertNull(object) / assertNotNull(object)
- assertThrows(expectedType, executable)
Annotations
@Test
: Marks a method as a test case@BeforeEach
: Executes before each test method@AfterEach
: Executes after each test method@BeforeAll
: Executes once before all test methods@AfterAll
: Executes once after all test methods
Mocking
- Replacing real dependencies with controlled substitutes during unit testing
- Allows you to isolate the unit under test from external factors
- See Mockito frameworks
Mutation Testing
- Evaluate the effectiveness of your tests
- Introduces small changes (mutations) to your code
- Checks if your tests can detect these changes
- Mutations are automatically seeded into your code,
- then your tests are run.
- If your tests fail then the mutation is killed
- if your tests pass then the mutation lived
- The quality of your tests can be gauged from the percentage of mutations killed
Replace :
+
with-
>
with>=
- …