CI with GitHub Actions for Java: Running Unit Tests with Maven Step by Step

🧩 Introduction
Automating tests is one of the key pillars of quality in modern software systems. In Java projects using Spring Boot, ensuring that unit tests run on every change is essential to maintain application reliability.
In this article, we will configure a simple CI (Continuous Integration) pipeline using GitHub Actions, focused on running unit tests with Maven.
We will use as an example a project based on Domain Driven Design (DDD) with Java 21 and MapStruct.
🚀 What is GitHub Actions?
GitHub Actions is a native GitHub tool that allows you to automate workflows directly within your repository.
With it, you can:
- Automatically run tests
- Build your application
- Publish artifacts
- Integrate with external tools
All triggered by events such as push or pull request.
🏗️ Project structure
Our project is organized as follows:
website-projects/
└─ ddd-java-spring-dto-model-entity/
├─ pom.xml
└─ src/
⚙️ Creating the GitHub Actions workflow
To configure the pipeline, we create the following file:
.github/workflows/java-tests.yml
📄 GitHub Actions YAML
name: Java Unit Tests
on:
push:
branches: [ "main" ]
paths:
- "ddd-java-spring-dto-model-entity/**"
- ".github/workflows/java-tests.yml"
pull_request:
branches: [ "main" ]
paths:
- "ddd-java-spring-dto-model-entity/**"
- ".github/workflows/java-tests.yml"
jobs:
test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ddd-java-spring-dto-model-entity
steps:
- name: Checkout do código
uses: actions/checkout@v4
- name: Configurar Java 21
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '21'
cache: maven
- name: Executar testes unitários
run: mvn -B test
🔍 Workflow breakdown
🔹 name
name: Java Unit Tests
Defines the name displayed in GitHub Actions.
🔹 on (triggers)
on:
push:
pull_request:
The workflow runs when:
- code is pushed to the
mainbranch - a pull request is opened or updated
🔹 paths (important optimization)
paths:
- "ddd-java-spring-dto-model-entity/**"
👉 Ensures the pipeline runs only when changes occur in the project folder, avoiding unnecessary executions.
🔹 jobs
jobs:
test:
runs-on: ubuntu-latest
Defines a job that runs on a Linux machine.
🔹 working-directory (key point)
defaults:
run:
working-directory: ddd-java-spring-dto-model-entity
👉 This is critical:
Since the project is inside a subdirectory, we define the working directory so Maven can correctly locate the pom.xml.
🔹 checkout
- uses: actions/checkout@v4
Clones the repository into the runner.
🔹 Java setup
- uses: actions/setup-java@v5
Configures:
- Java 21
- Maven dependency caching
👉 This significantly improves build performance.
🔹 Running tests
run: mvn -B test
Runs unit tests.
-B→ batch mode (recommended for CI)
🔄 Pipeline flow
![]()
GitHub Actions Java Maven unit tests
💡 Best practices
- ✔️ Use dependency caching (already applied)
- ✔️ Limit execution using
paths - ✔️ Fix Java version (e.g., 21)
- ✔️ Keep the pipeline simple at first
🔥 Possible improvements
You can evolve this pipeline to include:
- 📊 Code coverage with JaCoCo
- 🧪 Integration tests
- 🐳 Docker build
- 🚀 Automatic deployment
🔗 Example project
👉 https://github.com/isacaguiar/website-projects
🧠 Conclusion
With just a few steps, we created an efficient CI pipeline for Java projects.
This approach:
- improves code quality
- reduces production issues
- makes your repository more professional
And best of all: everything is fully integrated into GitHub.
Share this content:
Let’s grow together in technology, career, and discipline.
Follow new articles on backend, architecture, performance, and the lessons that also come from sports. A space to share knowledge, consistency, and growth throughout the journey.