Power Your Software Testing with AI Agents and Cloud
The Native AI-Agentic Cloud Platform to Supercharge Quality Engineering. Test Intelligently and Ship Faster.
- TestMu AI (Formerly LambdaTest)
- /
- Learning Hub
- /
- JUnit Tutorial: Learn JUnit 5 and JUnit 6 Step by Step
JUnit Tutorial: Learn JUnit 5 and JUnit 6 Step by Step
JUnit tutorial for Java: what JUnit is, JUnit 5 setup, a first passing test, JUnit 4 vs 5 vs 6, and 20+ chapters on annotations, assertions, and Selenium.
Last Updated on:
To get started with JUnit, Java's standard open-source unit testing framework: install the JDK and set JAVA_HOME, add the junit-jupiter dependency to your Maven pom.xml or Gradle build, write a method annotated with @Test, verify results with assertions like assertEquals, then run the tests via your IDE, Maven Surefire, or Gradle.
JUnit 5 (Jupiter) is the version most teams write today. JUnit 6 arrived on September 30, 2025 and keeps the same Jupiter API you will learn here, raising the runtime baseline to Java 17.
This JUnit tutorial is a course of 20 chapters. This page explains what JUnit is, gets a first test running, and lays out the chapters in reading order. Each chapter goes deep on one topic, from annotations and assertions to parameterized tests, Mockito, and parallel Selenium runs, and links back here.
Overview
Which JUnit version should you use?
JUnit 6 if your project runs Java 17 or higher, since it is the current generation. Stay on JUnit 5 for Java 8 or 11.
What does a JUnit test suite need to run?
Four moving parts turn a plain Java class into a suite your build can execute.
- Jupiter dependency: The junit-jupiter artifact pulls in the API, the engine, and parameterized-test support.
- Lifecycle annotations: @Test marks the case, while @BeforeEach and @AfterEach set up and tear down state.
- Assertions: assertEquals, assertThrows, and assertAll decide whether the observed behaviour passes.
- Build tool runner: Maven Surefire or Gradle useJUnitPlatform() discovers and executes the tests.
- Reports: Surefire XML output feeds CI dashboards and tools such as Allure or ExtentReports.
What Is JUnit?
JUnit is the standard open-source Java testing framework. You mark methods with @Test, assert the expected result, and JUnit discovers and runs them from your IDE, Maven, or Gradle.
JUnit is one of the best Java testing frameworks, simplifying the creation of reliable and efficient automated tests. It excels in testing Java applications through features like support for diverse test cases, strong assertions, and comprehensive reporting.
Rooted in the xUnit family of frameworks, JUnit supports various test types, including unit, functional, and integration tests. While primarily used for unit testing, its flexibility allows it to handle broader testing scenarios, such as functional tests that evaluate overall system behavior and integration tests that assess component interactions.
How Does JUnit Work?
JUnit scans your compiled classes for annotated methods, builds a test plan, runs each method in isolation, and reports pass or fail through its built-in reporter or your build tool.
JUnit serves two purposes in automation testing: it confirms that the software behaves as intended and flags the cases where it does not, and it catches errors early, while the code that caused them is still fresh and cheap to fix.
JUnit supports unit tests (individual methods or classes), integration tests (component interactions), and system tests (end-to-end behaviour like web servers). Tests can run in parallel for efficiency, either from the command line or within IDEs like Eclipse and IntelliJ.
The framework simplifies testing through assertions that verify expected behaviour, test runners that execute and present results, test suites that group related tests for batch execution, and a built-in reporter that keeps outcomes readable.
Note: Run web app testing using the JUnit framework. Try TestMu AI Now!
JUnit Skills Covered in This Tutorial
By the end of the tutorial you will be able to:
- Add JUnit 5 or JUnit 6 to a Maven or Gradle project and run a first passing test.
- Use every Jupiter annotation and predict the order the lifecycle methods run in.
- Write assertions that fail with a useful message, including assertThrows and assertAll.
- Drive one test with many inputs using @ParameterizedTest, and organise suites with @Nested.
- Mock dependencies with Mockito and extend the lifecycle with @ExtendWith.
- Run tests from the command line and in parallel, and drive browsers with Selenium from JUnit.
- Tell JUnit 4, 5, and 6 apart, migrate between them, and decide when TestNG is the better fit.
Prerequisites
- Java 17 or newer for JUnit 6, or Java 8 or newer for JUnit 5, with JAVA_HOME set.
- Maven or Gradle, or an IDE such as IntelliJ IDEA or Eclipse that bundles one.
- Basic Java: classes, methods, and annotations. No prior testing framework is assumed.
- For the Selenium chapters, a current Chrome or Firefox. Selenium 4 downloads the driver for you.
JUnit Tutorial Chapters
Work through the groups in order. Each chapter is a runnable example with its own build file, and the reading time is shown next to it. The same list is in the Chapters panel on every page of the tutorial.
Getting Started
- Set Up the JUnit Environment: Install the JDK, add JUnit 5 with Maven or Gradle, and run a first test from your IDE. (13 min)
- JUnit Maven Dependency: junit-jupiter coordinates, the artifacts behind it, junit-bom, Surefire, Gradle, and Vintage for JUnit 4. (5 min)
- Write JUnit Test Cases: Structure a test class, name tests, and write cases that fail for the right reason. (17 min)
- Unit Testing in Java: What a unit test is, where JUnit fits, and habits that keep tests fast. (10 min)
- Run JUnit from the Command Line: Execute tests with the console launcher, Maven, and Gradle without an IDE. (20 min)
Annotations and Assertions
- JUnit Annotations: @Test, @BeforeEach, @BeforeAll and the rest, with the order they run in. (18 min)
- Ignore Tests with @Ignore and @Disabled: Skip a test or a whole class, and document why. (35 min)
- @RepeatedTest in JUnit 5: Run the same test many times and name each repetition. (10 min)
- JUnit Assertions: assertEquals, assertTrue, assertThrows, assertAll, and how to write clear failure messages. (25 min)
- JUnit ErrorCollector: Collect several failures in one test instead of stopping at the first. (20 min)
Parameterized and Structured Tests
- JUnit Parameterized Tests: Run one test with many inputs using @ParameterizedTest and its sources. (14 min)
- Nested Tests in JUnit 5: Group related tests into inner classes with @Nested. (24 min)
- JUnit Jupiter: What the Jupiter API and engine are, and how they run your tests. (21 min)
Running and Integrating
- Parallel Testing with JUnit 5: Turn on parallel execution in junit-platform.properties and run Selenium tests concurrently. (22 min)
- JUnit with Selenium: Drive a browser from a JUnit test and run it across browsers. (15 min)
- JUnit 5 with Mockito: Mock dependencies, verify calls, and wire Mockito in with MockitoExtension. (16 min)
- JUnit 5 Extensions: Hook into the test lifecycle with @ExtendWith and the extension model. (29 min)
Versions and Comparisons
- JUnit 4 vs JUnit 5 vs JUnit 6: What changed between versions and how to run JUnit 4 tests on the JUnit 5 platform. (18 min)
- What's New in JUnit 6: The JUnit 6 release: Java 17 baseline, removed APIs, and new features. (9 min)
- Migrate from JUnit 5 to JUnit 6: A step-by-step upgrade path with the build changes and the pitfalls. (18 min)
- JUnit 5 vs TestNG: Feature-by-feature comparison and which framework fits which project. (24 min)
- JUnit Interview Questions: Fifty-nine questions with answers, from basics to JUnit 5 internals. (26 min)
Setting Up JUnit
Five steps take you from an empty folder to a passing JUnit test. The Set Up the JUnit Environment chapter covers the same steps with screenshots, JAVA_HOME and CLASSPATH details, and the Eclipse route.
- Install a JDK. JUnit 6 needs Java 17 or newer; confirm it with java -version.
- Create a Maven or Gradle project in IntelliJ IDEA or Eclipse.
- Add the Jupiter dependency and a current Surefire plugin (the JUnit Maven Dependency chapter explains the artifacts, junit-bom, and Gradle). Maven:
Gradle users add testImplementation 'org.junit.jupiter:junit-jupiter:6.1.3' and test { useJUnitPlatform() } instead.<dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>6.1.3</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.6.0</version> </plugin> </plugins> </build> - Write a test class under src/test/java:
import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; class CalculatorTest { @Test void addsTwoNumbers() { Calculator calculator = new Calculator(); assertEquals(5, calculator.add(2, 3), "2 + 3 should be 5"); } } - Run it from the IDE, or from the command line:
Surefire prints a summary with the number of tests run, failed, and skipped, and writes XML reports to target/surefire-reports.mvn test
From here, the Write JUnit Test Cases chapter shows how to structure a test class and name tests, and Run JUnit from the Command Line covers the console launcher and Gradle.
JUnit Architecture
JUnit 5 is structured around several modules distributed across three distinct sub-projects, each serving a specific purpose. JUnit 6 keeps the same layout.

JUnit Platform
The JUnit Platform is the backbone for initiating testing frameworks on the Java Virtual Machine (JVM). It establishes the interface between JUnit and its users, including various build tools. That interface is what lets build tools discover and execute tests without knowing how each engine works.
The platform introduces the TestEngine API, a critical component for developing testing frameworks compatible with the JUnit Platform. Developers can implement custom TestEngines, directly incorporating third-party testing libraries into the JUnit ecosystem.
JUnit Jupiter
The Jupiter module introduces the programming and extension models for writing tests in JUnit 5 and 6. It brings new annotations that enhance test definition capabilities compared to JUnit 4, such as @DisplayName, @Nested, @Tag, @ExtendWith, and the @BeforeEach, @AfterEach, @BeforeAll, and @AfterAll lifecycle annotations that replace their JUnit 4 counterparts. The JUnit Jupiter chapter covers the module in depth.
JUnit Vintage
JUnit Vintage provides compatibility support for running tests built on JUnit 3 and JUnit 4 within the JUnit 5 platform. This ensures smooth migration for projects that rely on earlier JUnit versions.
JUnit 5 splits into three modules: the Platform that launches tests, Jupiter that provides the API you write against, and Vintage that runs legacy JUnit 3 and 4 suites.
Benefits of Using JUnit
JUnit offers a range of advantages, the main one being that it supports the development of testable code. Additional reasons to consider integrating JUnit into your software development workflow are discussed below.
- Code organization and readability. JUnit's structured approach allows developers to create clear and organized test suites that stay quick to navigate and understand.
- Error identification and resolution. Systematic test execution with JUnit helps developers catch and fix issues quickly, before they grow into larger problems.
- Enhanced software quality. Enforcing comprehensive testing methodologies helps ensure each part of the codebase behaves as intended, producing more reliable software.
- Efficiency and process improvement. Automating repetitive test cases frees developers to focus on more complex work, leading to an improved test process and a faster development cycle.
Incorporating JUnit promotes code reliability and contributes to code clarity, error resolution, software quality enhancement, and overall process efficiency in software development.
JUnit 4, 5, and 6 at a Glance
- JUnit 4 (2006) is a single jar with runners such as @RunWith, @Before and @After lifecycle methods, and @Ignore. It still runs everywhere, but it receives no new features.
- JUnit 5 (2017) split the framework into Platform, Jupiter, and Vintage, renamed the lifecycle annotations to @BeforeEach and @BeforeAll, and added assertThrows, assertAll, @ParameterizedTest, @Nested, @DisplayName, and the @ExtendWith extension model. It runs on Java 8 and newer.
- JUnit 6 (September 2025) keeps the Jupiter API, raises the baseline to Java 17, removes long-deprecated APIs, and aligns the version numbers of Platform, Jupiter, and Vintage. For most suites the upgrade is a dependency change rather than a rewrite.
The JUnit 4 vs JUnit 5 vs JUnit 6 chapter compares the three versions feature by feature and shows how to run JUnit 4 tests on the new platform. What's New in JUnit 6 and Migrate from JUnit 5 to JUnit 6 cover the latest release and the upgrade path.
JUnit with Selenium and Parallel Runs
JUnit and Selenium work independently, but pairing them gives browser tests lifecycle control, structured assertions, and reporting, which is why the combination is so common in cross-browser testing. A Selenium test in JUnit is an ordinary test class: @BeforeEach opens a WebDriver, the @Test method drives the page and asserts on it, and @AfterEach quits the driver.
Parallel execution is switched on in junit-platform.properties with junit.jupiter.execution.parallel.enabled=true, and tuned per class or method with @Execution(CONCURRENT). The JUnit with Selenium chapter builds the first browser test, and Parallel Testing with JUnit 5 runs it concurrently across browsers, locally and on a cloud grid.
If your project standardises on TestNG instead, the TestNG tutorial follows the same chapter structure, and the JUnit 5 vs TestNG chapter compares the two frameworks feature by feature.
Best Practices for JUnit Testing
These practices come from suites that got slow, flaky, or unreadable, and what stopped it. Each one targets a specific failure mode rather than general advice.
- Keep tests simple and focused. A unit test checks one behaviour, reads in a few seconds, and says exactly what failed.
- Use descriptive test names. Name methods after the behaviour, and use @DisplayName when the sentence needs spaces or punctuation.
- Avoid random values at runtime. Random inputs can expose edge cases, but they make failures hard to reproduce. Enumerate the cases with @ParameterizedTest instead.
- Never test implementation details. Assert on behaviour and outputs, not on private state, so refactoring does not break the suite.
- Handle edge cases. Nulls, empty collections, and boundary values belong in the suite from the first version.
- Apply Arrange, Act, Assert. Set up the data, perform the one operation under test, then verify the result, in that order and nothing else.
Adapting to these best practices ensures that your JUnit tests are effective, maintainable, and provide meaningful insights into the behavior of your code.
Conclusion
JUnit remains the most widely used framework for Java unit testing. JUnit 5 gave it a modular architecture, improved annotations, richer assertions, and parameterized and parallel tests, and JUnit 6 continues that direction on a Java 17 baseline, so the Jupiter API you learn here carries forward unchanged.
Start with the first chapter, Set Up the JUnit Environment, or jump to any chapter in the list above. Every chapter links back to this page, and the Chapters panel keeps your place as you move through the tutorial.
Author
Saniya Gazala is a Product Marketing Manager and Community Evangelist at TestMu AI with 2+ years of experience in software QA, manual testing, and automation adoption. She holds a B.Tech in Computer Science Engineering. At TestMu AI, she leads content strategy, community growth, and test automation initiatives, having managed a 5-member team and contributed to certification programs using Selenium, Cypress, Playwright, Appium, and KaneAI. Saniya has authored 15+ articles on QA and holds certifications in Automation Testing, Six Sigma Yellow Belt, Microsoft Power BI, and multiple automation tools. She also crafted hands-on problem statements for Appium and Espresso. Her work blends detailed execution with a strategic focus on impact, learning, and long-term community value.
Reviewer
Srinivasan Sekar is Director of Engineering at TestMu AI (formerly LambdaTest), where he leads engineering and open-source initiatives behind the Selenium and Appium automation grid and owns TestMu AI's MCP Server. A committer to Appium and a contributor to Selenium, WebdriverIO, Taiko, and AppiumTestDistribution, he brings over 15 years of experience in quality engineering and open-source technologies. He is the author of the Apress book 'The MCP Standard: A Developer's Guide to Building Universal AI Tools with the Model Context Protocol,' a Certified Kubernetes and Cloud Native Associate, and an international conference speaker. Before TestMu AI he spent over eight years at Thoughtworks as a Principal Consultant and Quality Architect. Srinivasan holds a B.Tech in Information Technology from Anna University.
JUnit Tutorial FAQs
Did you find this page helpful?
More Related Learning Hubs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance
- Advanced access controls
- Advanced data retention rules
- Advanced Local Testing
- Premium Support options
- Early access to beta features
- Private Slack Channel
- Unlimited Manual Accessibility DevTools Tests




