eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

Partner – Diagrid – NPI (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

In this article, we’ll introduce the TestNG testing framework.

We’ll focus on: framework setup, writing simple test case and configuration, test execution, test reports generation, and concurrent test execution.

2. Setup

Let’s start by adding the Maven dependency in our pom.xml file:

<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>7.1.0</version>
    <scope>test</scope>
</dependency>

The latest version can be found in the Maven repository.

When using Eclipse, the TestNG plugin may be downloaded and installed from the Eclipse Marketplace.

3. Writing a Test Case

To write a test using TestNG, we just need to annotate the test method with org.testng.annotations.Test annotation:

@Test
public void givenNumber_whenEven_thenTrue() {
    assertTrue(number % 2 == 0);
}

4. Test Configurations

While writing test cases, often we need to execute some configuration or initialization instructions before test executions, and also some cleanup after completion of tests. TestNG provides a number of initialization and clean-up features at method, class, group and suite levels:

@BeforeClass
public void setup() {
    number = 12;
}

@AfterClass
public void tearDown() {
    number = 0;
}

The setup() method annotated with @BeforeClass annotations will be invoked before execution of any methods of that test class, and tearDown() after execution all methods of the test class.

Similarly, we can use the @BeforeMethod, @AfterMethod, @Before/AfterGroup, @Before/AfterTest and @Before/AfterSuite annotations for any configuration at method, group, test and suite levels.

5. Test Execution

We can run the test cases with Maven’s “test” command, it will execute all the test cases annotated with @Test putting them to a default test suite. We can also run test cases from the TestNG test suite XML files, by using the maven-surefire-plugin:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
    <configuration>
        <suiteXmlFiles>
            <suiteXmlFile>
               src\test\resources\test_suite.xml
            </suiteXmlFile>
        </suiteXmlFiles>
    </configuration>
</plugin>

Note that if we have multiple XML files, covering all test cases, we can add all of them in the suiteXmlFiles tag:

<suiteXmlFiles>
    <suiteXmlFile>
      src/test/resources/parametrized_test.xml
    </suiteXmlFile>
    <suiteXmlFile>
      src/test/resources/registration_test.xml
    </suiteXmlFile>
</suiteXmlFiles>

In order to run the test standalone, we need to have the TestNG library in the classpath and the compiled test class along with the XML configuration file:

java org.testng.TestNG test_suite.xml

6. Grouping Tests

Tests can be run in groups, for example out of 50 test cases 15 can be grouped together and executed leaving others as is.

In TestNG grouping tests in suites are done using XML file:

<suite name="suite">
    <test name="test suite">
        <classes>
            <class name="com.baeldung.RegistrationTest" />
            <class name="com.baeldung.SignInTest" />
        </classes>
    </test>
</suite>

Notice that, both the test classes RegistrationTest, SignInTest now belongs to the same suite and once suite is executed, test cases in this class will get executed.

Apart from test suites, we can also create test groups in TestNG, where instead of test classes methods are grouped together. In order to do that, add the groups parameter in the @Test annotation:

@Test(groups = "regression")
public void givenNegativeNumber_sumLessthanZero_thenCorrect() {
    int sum = numbers.stream().reduce(0, Integer::sum);
 
    assertTrue(sum < 0);
}

Let’s use an XML to execute the groups:

<test name="test groups">
    <groups>
        <run>
            <include name="regression" />
        </run>
    </groups>
    <classes>
        <class
          name="com.baeldung.SummationServiceTest" />
    </classes>
</test>

This will execute the test method tagged with group regression, in the SummationServiceTest class.

7. Parameterized Tests

Parameterized unit tests are used for testing the same code under several conditions. With the help of parameterized unit tests, we can set up a test method that obtains data from some data source. The main idea is to make the unit test method reusable and to test with a different set of inputs.

In TestNG, we can parametrize tests using @Parameter or @DataProvider annotation. While using the XML file annotate the test method with @Parameter:

@Test
@Parameters({"value", "isEven"})
public void
  givenNumberFromXML_ifEvenCheckOK_thenCorrect(int value, boolean isEven) {
    
    assertEquals(isEven, value % 2 == 0);
}
And provide the data using XML file:
<suite name="My test suite">
    <test name="numbersXML">
        <parameter name="value" value="1"/>
        <parameter name="isEven" value="false"/>
        <classes>
            <class name="baeldung.com.ParametrizedTests"/>
        </classes>
    </test>
</suite>

Using data from XML file is useful, but we often need more complex data. @DataProvider annotation is used to handle these scenarios, which can be used to map complex parameter types for testing methods.@DataProvider for primitive data types:

@DataProvider(name = "numbers")
public static Object[][] evenNumbers() {
    return new Object[][]{{1, false}, {2, true}, {4, true}};
}
 
@Test(dataProvider = "numbers")
public void 
  givenNumberFromDataProvider_ifEvenCheckOK_thenCorrect(Integer number, boolean expected) {    
    assertEquals(expected, number % 2 == 0);
}

@DataProviderfor objects:

@Test(dataProvider = "numbersObject")
public void 
  givenNumberObjectFromDataProvider_ifEvenCheckOK_thenCorrect(EvenNumber number) {  
    assertEquals(number.isEven(), number.getValue() % 2 == 0);
}
 
@DataProvider(name = "numbersObject")
public Object[][] parameterProvider() {
    return new Object[][]{{new EvenNumber(1, false)},
      {new EvenNumber(2, true)}, {new EvenNumber(4, true)}};
}

Using this, any object that has to be tested can be created and used in the test. This is mostly useful for integration test cases.

8. Ignoring Test Cases

We sometimes want not to execute a certain test case, temporarily during the development process. This can be done adding enabled=false, in the @Test annotation:

@Test(enabled=false)
public void givenNumbers_sumEquals_thenCorrect() { 
    int sum = numbers.stream.reduce(0, Integer::sum);
    assertEquals(6, sum);
}

9. Dependent Tests

Let’s consider a scenario, where if the initial test case fails, all subsequent test cases should be executed, and rather be marked as skipped. TestNG provides this feature with the dependsOnMethods parameter of the @Test annotation:

@Test
public void givenEmail_ifValid_thenTrue() {
    boolean valid = email.contains("@");
 
    assertEquals(valid, true);
}
 
@Test(dependsOnMethods = {"givenEmail_ifValid_thenTrue"})
public void givenValidEmail_whenLoggedIn_thenTrue() {
    LOGGER.info("Email {} valid >> logging in", email);
}

Notice that, the login test case depends on the email validation test case. Thus, if email validation fails the login test will be skipped.

10. Concurrent Test Execution

TestNG allows tests to run in parallel or in multi-threaded mode, thus providing a way to test these multi-threaded pieces of code.

You can configure, for methods, classes, and suites to run in their own threads reducing the total execution time.

10.1. Classes and Methods in Parallel

To run test classes in parallel, mention the parallel attribute in the suite tag in XML configuration file, with value classes:

<suite name="suite" parallel="classes" thread-count="2">
    <test name="test suite">
        <classes>
	    <class name="baeldung.com.RegistrationTest" />
            <class name="baeldung.com.SignInTest" />
        </classes>
    </test>
</suite>

Note that, if we have multiple test tags in the XML file, these tests can also be run in parallel, by mentioning parallel =” tests”. Also to execute individual methods in parallel, mention parallel =” methods”.

10.2. Multi-Threaded Execution of Test Method

Let’s say we need to test the behavior of a code when running in multiple threads. TestNG allows to run a test method in multiple threads:

public class MultiThreadedTests {
    
    @Test(threadPoolSize = 5, invocationCount = 10, timeOut = 1000)
    public void givenMethod_whenRunInThreads_thenCorrect() {
        int count = Thread.activeCount();
 
        assertTrue(count > 1);
    }
}

The threadPoolSize indicates that the method will run in n number of threads as mentioned. The invocationCount and timeOut indicate that the test will be executed multiple times and fail the test if it takes more time.

11. Functional Testing

TestNG comes with features which can be used for functional testing as well. In conjunction with Selenium, it can either be used to test functionalities of a web application or used for testing web services with HttpClient.

More details about functional testing with Selenium and TestNG is available here. Also some more pieces of stuff on integration testing in this article.

12. Conclusion

In this article, we had a quick look at how to setup TestNG and execute a simple test case, generate reports, concurrent execution of test cases and also a little about functional programming. For more features like dependent tests, ignoring test cases, test groups and suites you can refer our JUnit vs TestNG article here.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)