Spring Boot TestNG Tutorial

Introduction

TestNG is a powerful testing framework inspired by JUnit and NUnit, designed to simplify a broad range of testing needs, from unit testing to integration testing. It introduces new functionalities that make it more powerful and easier to use, such as annotations, flexible test configurations, test groups, and parallel execution. This tutorial will demonstrate how to integrate TestNG into a Spring Boot application with step-by-step examples.

To learn more about TestNG, check out this guide: TestNG.

Prerequisites

  1. Java Development Kit (JDK) 17 or later
  2. Apache Maven installed
  3. An IDE like IntelliJ IDEA or Eclipse

Step 1: Create a Spring Boot Project

You can create a Spring Boot project using Spring Initializr or your IDE.

Using Spring Initializr

  1. Go to Spring Initializr.
  2. Select the following options:
    • Project: Maven Project
    • Language: Java
    • Spring Boot: 3.0.0 or later
    • Group: com.example
    • Artifact: testng-demo
    • Name: testng-demo
    • Package name: com.example.testngdemo
    • Packaging: Jar
    • Java: 17 or later
  3. Add the following dependencies:
    • Spring Web
    • Spring Data JPA
    • H2 Database
  4. Click "Generate" to download the project zip file.
  5. Extract the zip file and open the project in your IDE.

Step 2: Add TestNG Dependency

Add the following dependencies to your pom.xml file:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Starter Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- H2 Database -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- Spring Boot Starter Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- TestNG -->
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.5</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Step 3: Configure Application Properties

Add the following properties to src/main/resources/application.properties:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

Step 4: Create Entity and Repository Classes

Create the Employee Entity

Create a new Java class named Employee in the com.example.testngdemo package:

package com.example.testngdemo;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    // Getters and Setters
    public Employee() {}

    public Employee(String name, String email) {
        this.name = name;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

Create the Employee Repository

Create a new Java interface named EmployeeRepository in the com.example.testngdemo package:

package com.example.testngdemo;

import org.springframework.data.jpa.repository.JpaRepository;

public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}

Step 5: Create the Service Class

EmployeeService

Create a new Java class named EmployeeService in the com.example.testngdemo package:

package com.example.testngdemo;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
public class EmployeeService {

    private final EmployeeRepository employeeRepository;

    public EmployeeService(EmployeeRepository employeeRepository) {
        this.employeeRepository = employeeRepository;
    }

    public List<Employee> findAll() {
        return employeeRepository.findAll();
    }

    public Optional<Employee> findById(Long id) {
        return employeeRepository.findById(id);
    }

    @Transactional
    public Employee save(Employee employee) {
        return employeeRepository.save(employee);
    }

    @Transactional
    public void deleteById(Long id) {
        employeeRepository.deleteById(id);
    }
}

Step 6: Create the Controller Class

EmployeeController

Create a new Java class named EmployeeController in the com.example.testngdemo package:

package com.example.testngdemo;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/employees")
public class EmployeeController {

    private final EmployeeService employeeService;

    public EmployeeController(EmployeeService employeeService) {
        this.employeeService = employeeService;
    }

    @GetMapping
    public List<Employee> getAllEmployees() {
        return employeeService.findAll();
    }

    @GetMapping("/{id}")
    public ResponseEntity<Employee> getEmployeeById(@PathVariable Long id) {
        return employeeService.findById(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }

    @PostMapping
    public Employee createEmployee(@RequestBody Employee employee) {
        return employeeService.save(employee);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Employee> updateEmployee(@PathVariable Long id, @RequestBody Employee employee) {
        return employeeService.findById(id)
                .map(existingEmployee -> {
                    employee.setId(existingEmployee.getId());
                    return ResponseEntity.ok(employeeService.save(employee));
                })
                .orElse(ResponseEntity.notFound().build());
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteEmployee(@PathVariable Long id) {
        return employeeService.findById(id)
                .map(employee -> {
                    employeeService.deleteById(id);
                    return ResponseEntity.noContent().build();
                })
                .orElse(ResponseEntity.notFound().build());
    }
}

Step 7: Create the Main Application Class

Create a main application class named TestngDemoApplication in the com.example.testngdemo package:

package com.example.testngdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestngDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestngDemoApplication.class, args);
    }
}

Explanation: The TestngDemoApplication class contains the main method, which is the entry point of the Spring Boot application. The @SpringBootApplication annotation is a convenience annotation that adds all the following:

  • @Configuration: Tags the class as a source of bean definitions for the application context.
  • @EnableAutoConfiguration: Tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings.
  • @ComponentScan: Tells Spring to look for other components, configurations, and services in the specified package.

Step 8: Create TestNG Test Classes

Test the EmployeeService

Create a new test class named EmployeeServiceTest in the src/test/java/com/example/testngdemo package:

package com.example.testngdemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.Test;

import java.util.List;
import java.util.Optional;

import static org.testng.Assert.*;

@SpringBootTest
public class EmployeeServiceTest extends AbstractTestNGSpringContextTests {

    @Autowired
    private EmployeeService employeeService;

    @Test
    public void testFindAll() {
        List<Employee> employees = employeeService.findAll();
        assertNotNull(employees);
        assertTrue(employees.isEmpty());
    }

    @Test
    public void testSave() {
        Employee employee = new Employee("Amit Sharma", "amit.sharma@example.com");
        Employee savedEmployee = employeeService.save



(employee);
        assertNotNull(savedEmployee.getId());
        assertEquals(savedEmployee.getName(), "Amit Sharma");
    }

    @Test
    public void testFindById() {
        Employee employee = new Employee("Rohit Sharma", "rohit.sharma@example.com");
        Employee savedEmployee = employeeService.save(employee);
        Optional<Employee> foundEmployee = employeeService.findById(savedEmployee.getId());
        assertTrue(foundEmployee.isPresent());
        assertEquals(foundEmployee.get().getName(), "Rohit Sharma");
    }

    @Test
    public void testDeleteById() {
        Employee employee = new Employee("Suresh Kumar", "suresh.kumar@example.com");
        Employee savedEmployee = employeeService.save(employee);
        employeeService.deleteById(savedEmployee.getId());
        Optional<Employee> foundEmployee = employeeService.findById(savedEmployee.getId());
        assertFalse(foundEmployee.isPresent());
    }
}

Explanation:

  • @SpringBootTest: Used to load the complete application context.
  • extends AbstractTestNGSpringContextTests: Integrates TestNG with Spring Boot.
  • @Test: Indicates a TestNG test method.

Step 9: Run the Tests

You can run the tests using your IDE or by executing the following command in the terminal:

mvn test

You should see an output indicating that all tests have passed successfully.

Conclusion

In this tutorial, we demonstrated how to integrate TestNG into a Spring Boot application and covered various use cases, including complex examples. We created a simple Spring Boot application with Employee entity, repository, service, and controller layers, and wrote TestNG test cases to test the service layer. 

By following these steps, you can efficiently use TestNG to test your Spring Boot applications, ensuring robust and reliable code.

Comments