This guide explains how to run tests, generate test reports, and view code coverage for the Autonova Backend microservices.
- Overview
- Quick Start
- Test Types
- Running Tests
- Test Reports
- Code Coverage
- CI/CD Integration
- Troubleshooting
The testing infrastructure includes:
- JUnit 5 for unit and integration tests
- Mockito for mocking dependencies
- TestContainers for integration tests with real databases/messaging
- REST Assured for API testing
- JaCoCo for code coverage reporting
- Maven Surefire for unit test execution
- Maven Failsafe for integration test execution
- Line Coverage: 60% minimum
- Branch Coverage: 50% minimum
# Make script executable (first time only)
chmod +x run-tests.sh
# Run all tests and generate reports
./run-tests.shAfter running tests, open these files in your browser:
- Unit Tests:
<service>/target/site/surefire-report.html - Integration Tests:
<service>/target/site/failsafe-report.html - Code Coverage:
<service>/target/site/jacoco/index.html
- Files ending with
Test.javaorTests.java - Fast, isolated tests with mocked dependencies
- Run with:
mvn test
- Files ending with
IT.javaorIntegrationTest.java - Use TestContainers for real database/messaging
- Run with:
mvn integration-test
# Run all tests
./run-tests.sh
# Run only unit tests
./run-tests.sh -t unit
# Run only integration tests
./run-tests.sh -t integration
# Run tests for specific services
./run-tests.sh -s customer-service,auth-service
# Skip coverage threshold checks (useful during development)
./run-tests.sh -c
# Run without generating HTML reports
./run-tests.sh -n# Unit tests only
mvn clean test
# Integration tests only
mvn clean integration-test
# All tests with coverage
mvn clean verify
# Skip coverage checks
mvn clean verify -Djacoco.skip=true# Navigate to service directory
cd customer-service
# Run unit tests
mvn test
# Run all tests with coverage
mvn verify
# Generate HTML reports
mvn surefire-report:report site -DgenerateReports=falseAfter running tests, the following reports are generated:
Location: target/site/surefire-report.html
Contains:
- Test execution summary
- Pass/fail status for each test
- Execution time
- Error messages and stack traces
Generate manually:
mvn surefire-report:reportLocation: target/site/failsafe-report.html
Contains:
- Integration test execution results
- TestContainers logs
- Database/messaging test results
Generate manually:
mvn failsafe-report:failsafe-report-onlyLocation: target/site/jacoco/index.html
Contains:
- Line coverage percentage
- Branch coverage percentage
- Package-level breakdown
- Class-level details
- Missed/covered lines highlighted
Additional JaCoCo Reports:
target/site/jacoco-merged/index.html- Combined unit + integration coveragetarget/jacoco.exec- Binary coverage data (unit tests)target/jacoco-it.exec- Binary coverage data (integration tests)target/jacoco-merged.exec- Merged binary data
Location:
target/surefire-reports/*.xml- Unit test resultstarget/failsafe-reports/*.xml- Integration test results
These XML files are used by CI/CD tools like Jenkins, GitHub Actions, GitLab CI.
# Customer service unit tests
open customer-service/target/site/surefire-report.html
# Customer service coverage
open customer-service/target/site/jacoco/index.html
# All services (opens in browser)
find . -name "surefire-report.html" -path "*/target/site/*" | xargs open# Generate complete site with all reports
mvn site
# View at target/site/index.htmlJaCoCo measures:
- Line Coverage: Percentage of code lines executed
- Branch Coverage: Percentage of decision branches taken
- Instruction Coverage: Bytecode instruction coverage
- Complexity Coverage: Cyclomatic complexity coverage
- Method Coverage: Methods invoked vs total methods
- Class Coverage: Classes instantiated vs total classes
Configured in pom.xml:
<jacoco.line.coverage>0.60</jacoco.line.coverage>
<jacoco.branch.coverage>0.50</jacoco.branch.coverage>Build fails if coverage is below threshold. Override with:
mvn verify -Djacoco.skip=true- Identify gaps: Open
target/site/jacoco/index.html - Navigate to classes: Click package → class
- View missed lines: Red = not covered, Green = covered, Yellow = partial
- Write tests: Focus on red/yellow lines
- Re-run:
mvn clean verify
# Generate coverage for all services
mvn clean verify
# Aggregate reports (view each service separately)
for service in */; do
echo "Coverage for $service:"
open "$service/target/site/jacoco/index.html"
donename: Test and Coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Run Tests
run: mvn clean verify
- name: Generate Coverage Report
run: mvn jacoco:report
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: ./target/site/jacoco/jacoco.xml
- name: Publish Test Report
uses: mikepenz/action-junit-report@v3
if: always()
with:
report_paths: '**/target/surefire-reports/TEST-*.xml'
- name: Upload Test Results
uses: actions/upload-artifact@v3
if: always()
with:
name: test-results
path: |
**/target/surefire-reports/
**/target/failsafe-reports/
**/target/site/jacoco/test:
stage: test
script:
- mvn clean verify
artifacts:
when: always
reports:
junit:
- "**/target/surefire-reports/TEST-*.xml"
- "**/target/failsafe-reports/TEST-*.xml"
coverage_report:
coverage_format: jacoco
path: "**/target/site/jacoco/jacoco.xml"
paths:
- "**/target/site/jacoco/"
- "**/target/surefire-reports/"
coverage: '/Total.*?([0-9]{1,3})%/'pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'mvn clean verify'
}
}
stage('Publish Reports') {
steps {
junit '**/target/surefire-reports/*.xml'
jacoco(
execPattern: '**/target/jacoco.exec',
classPattern: '**/target/classes',
sourcePattern: '**/src/main/java'
)
publishHTML(target: [
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'target/site',
reportFiles: 'surefire-report.html',
reportName: 'Test Report'
])
}
}
}
}[ERROR] Rule violated for bundle: Minimum line coverage is 0.60, but was 0.45
Solution A: Write more tests to increase coverage Solution B: Temporarily skip check:
mvn verify -Djacoco.skip=trueCould not find a valid Docker environment
Solution: Ensure Docker is running
# Check Docker
docker ps
# Start Docker (Mac/Linux)
systemctl start dockerCaused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement
Solution: Escape reserved keywords in entities:
@Column(name = "`year`") // Escape reserved keyword
private Integer year;com.rabbitmq.client.PossibleAuthenticationFailureException: Possibly caused by authentication failure
Solution: Tests should use @TestConfiguration with embedded RabbitMQ or mock:
@TestConfiguration
static class TestConfig {
@Bean
public ConnectionFactory connectionFactory() {
return mock(ConnectionFactory.class);
}
}java.lang.OutOfMemoryError: Java heap space
Solution: Already configured in parent POM:
<argLine>@{argLine} -Xmx1024m</argLine>Increase if needed in specific service POM:
<argLine>@{argLine} -Xmx2048m</argLine># If reports are missing, generate manually
mvn surefire-report:report
mvn site -DgenerateReports=false# Run with verbose output
mvn test -X
# Run specific test
mvn test -Dtest=CustomerServiceTest
# Run tests matching pattern
mvn test -Dtest=*ServiceTestIf experiencing weird issues:
# Clean all build artifacts
mvn clean
# Clean and rebuild
mvn clean install
# Clean specific service
cd customer-service && mvn clean- Use dependency injection
- Avoid static methods
- Keep methods small and focused
- Use interfaces for dependencies
// Unit tests
CustomerServiceTest.java
VehicleServiceTest.java
// Integration tests
CustomerServiceIT.java
DatabaseIntegrationIT.java@Test
@DisplayName("Should create customer when valid data provided")
void shouldCreateCustomer_WhenValidData() {
// Given
Customer customer = createValidCustomer();
// When
Customer result = customerService.create(customer);
// Then
assertThat(result.getId()).isNotNull();
}// Mock dependencies
@Mock
private CustomerRepository repository;
@InjectMocks
private CustomerService service;
// Use BDD style
given(repository.findById(1L)).willReturn(Optional.of(customer));
// Verify interactions
verify(repository).save(any(Customer.class));@Testcontainers
class CustomerServiceIT {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
.withDatabaseName("test")
.withUsername("test")
.withPassword("test");
@Test
void integrationTest() {
// Test with real database
}
}# Quick Reference
./run-tests.sh # Run all tests
./run-tests.sh -t unit # Unit tests only
./run-tests.sh -s customer-service # Specific service
mvn verify # All tests with coverage
mvn test # Unit tests only
open */target/site/jacoco/index.html # View coverage