Mutation Testing with PIT for Spring Boot Applications
Unit testing is critical to building reliable software, especially in modern Java applications powered by Spring Boot. But having tests isn’t the same as having effective tests. Mutation testing, especially with PIT (Pitest), helps ensure your tests truly validate your code by deliberately introducing bugs and checking whether your tests catch them. In this guide, we’ll show you how to set up PIT, interpret results, and improve your test quality.
1. What is Mutation Testing?
Mutation testing involves making small, controlled changes to your source code—called mutations—and running your tests. If the tests fail, the mutation is killed. If they pass, the mutation survives, meaning the test suite likely missed a case.
Example
public boolean isAdult(int age) { return age >= 18; }
A mutation might change >=
to >
:
public boolean isAdult(int age) { return age > 18; }
If this change doesn’t cause any test to fail, your tests may not be properly checking boundary cases.
2. Why Use PIT for Spring Boot?
PIT is fast, integrates well with Maven/Gradle, and supports frameworks like JUnit and TestNG. It’s particularly effective in Spring Boot apps where codebases can be large and logic dense.
- Uncovers weak test assertions
- Encourages behavior-driven tests
- Helps justify test coverage
3. Setting Up PIT with Maven
1. Add Plugin to pom.xml
<build> <plugins> <plugin> <groupId>org.pitest</groupId> <artifactId>pitest-maven</artifactId> <version>1.15.0</version> <configuration> <targetClasses> <param>com.example.*</param> </targetClasses> <targetTests> <param>com.example.*Test</param> </targetTests> <threads>4</threads> <mutationThreshold>85</mutationThreshold> <coverageThreshold>85</coverageThreshold> </configuration> </plugin> </plugins> </build>
2. Run Mutation Tests
mvn org.pitest:pitest-maven:mutationCoverage
3. Analyze the Report
PIT generates a report in target/pit-reports
:
- See which lines mutated
- Visualize killed/survived mutants
- Use graphs to find weak spots
4. Example: Service Under Test
@Service public class CalculatorService { public int add(int a, int b) { return a + b; } public int divide(int a, int b) { if (b == 0) throw new IllegalArgumentException("Division by zero"); return a / b; } }
JUnit 5 Test Class
@SpringBootTest public class CalculatorServiceTest { @Autowired private CalculatorService service; @Test void testAdd() { assertEquals(5, service.add(2, 3)); } @Test void testDivide() { assertThrows(IllegalArgumentException.class, () -> service.divide(10, 0)); } @Test void testDivideNormal() { assertEquals(5, service.divide(10, 2)); } }
PIT may mutate +
to -
or remove the exception. Effective tests will catch these mutations.
5. Tips for Effective Mutation Testing
- Start with core business logic — test controllers later.
- Avoid over-mocking — especially in service and repository layers.
- Use filters to skip low-value mutations:
<excludedClasses> <param>com.example.dto.*</param> </excludedClasses>
Enable Parallel Execution
<threads>4</threads>
Raise Quality Bars
<mutationThreshold>85</mutationThreshold> <coverageThreshold>85</coverageThreshold>
6. CI Integration
Add PIT to your build pipelines in Jenkins, GitHub Actions, or GitLab CI:
mvn verify mvn org.pitest:pitest-maven:mutationCoverage
7. Pros and Cons
✅ Pros
- Reveals untested edge cases
- Boosts confidence in test coverage
- Improves test design discipline
❌ Cons
- Can slow down builds
- Noise from trivial mutations
- Harder to interpret than code coverage alone
8. Resources
9. Conclusion
Mutation testing with PIT helps uncover weak or ineffective tests in your Spring Boot application. Unlike simple code coverage tools, PIT tells you whether your tests actually validate logic under mutation. By integrating PIT into your workflow and CI pipeline, you build higher quality code that’s resilient to change and bugs.
Nice article, but som text seems to be missing from the code snippets.
Thank you for the feedback! You’re absolutely right. Looks like some snippets didn’t render properly when I moved the code from my IDE to the publishing platform. I’ve corrected everything now. Really appreciate you pointing it out! I’ll make sure to double-check formatting in future posts. Thanks again!