Saturday 5 October 2019

Spring boot: Writing integration tests to controllers


Step 1: Create a test class and annotate it with @RunWith and @SpringBootTest annotations

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
public class EmployeeControllerIntegrationTest {

 .....
 .....

}


@RunWith(SpringJUnit4ClassRunner.class)
Above statement tells to run the test with SpringJUnit4ClassRunner.

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
Tells to run the spring boot application on any randomly available port.

@ActiveProfiles("test")
Tells to use the test profile for these test cases.

Step 2: Inject the controller.
@Autowired
private EmployeeController empController;

Step 3:  Call the controller methods to test the response.
ResponseEntity<Employee> response = empController.save(emp1);
Employee persistedEmployee = response.getBody();

Find the below working application.

Employee.java
package com.sample.app.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "employees")
public class Employee {

 @Id
 @GeneratedValue
 @Column(name = "employee_name")
 private Integer id;

 @Column(name = "first_name")
 private String firstName;

 @Column(name = "last_name")
 private String lastName;

 public Integer getId() {
  return id;
 }

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

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

}


EmployeeDao.java
package com.sample.app.dao;

import java.util.List;

import com.sample.app.model.Employee;

public interface EmployeeDao {

 public Employee save(Employee emp);
 
 public List<Employee> all();
}


EmployeeDaoImpl.java
package com.sample.app.dao.impl;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

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

import com.sample.app.dao.EmployeeDao;
import com.sample.app.model.Employee;

@Repository
public class EmployeeDaoImpl implements EmployeeDao {
 @PersistenceContext
 private EntityManager entityManager;

 @Override
 @Transactional
 public Employee save(Employee emp) {
  entityManager.persist(emp);
  entityManager.flush();
  int id = emp.getId();

  return entityManager.find(Employee.class, id);

 }

 @Override
 public List<Employee> all() {
  Query query = entityManager.createQuery("select e from Employee e", Employee.class);
  return query.getResultList();
 }

}


EmployeeService.java
package com.sample.app.service;

import java.util.List;

import com.sample.app.model.Employee;

public interface EmployeeService {
 public Employee save(Employee emp);

 public List<Employee> all();
}


EmployeeServiceImpl.java
package com.sample.app.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sample.app.dao.EmployeeDao;
import com.sample.app.model.Employee;
import com.sample.app.service.EmployeeService;

@Service
public class EmployeeServiceImpl implements EmployeeService {

 @Autowired
 EmployeeDao empDao;

 @Override
 public Employee save(Employee emp) {
  return empDao.save(emp);
 }

 @Override
 public List<Employee> all() {
  return empDao.all();
 }

}


HomeController.java
package com.sample.app.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController {
 @RequestMapping("/")
 public String homePage() {
  return "Welcome to Spring boot Application Development";
 }

}


EmployeeController.java
package com.sample.app.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.sample.app.model.Employee;
import com.sample.app.service.EmployeeService;

@RestController
@RequestMapping("api/v1/")
public class EmployeeController {

 @Autowired
 private EmployeeService empService;

 @RequestMapping(value = "employees", method = RequestMethod.GET)
 public ResponseEntity<List<Employee>> allEmployees() {
  return ResponseEntity.ok(empService.all());
 }

 @RequestMapping(value = "employees", method = RequestMethod.POST)
 public ResponseEntity<Employee> save(@RequestBody Employee emp) {
  Employee persistedEmp = empService.save(emp);
  return ResponseEntity.status(HttpStatus.CREATED).body(persistedEmp);
 }

}


App.java
package com.sample.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing
public class App {

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

}


application.properties
logging.level.root=WARN
logging.level.org.hibernate=ERROR

## H2 specific properties
spring.h2.console.enabled=true
spring.h2.console.path=/h2

spring.datasource.url=jdbc:h2:file:~/db/myOrg.db;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;

spring.datasource.username=krishna
spring.datasource.password=password123

spring.datasource.driverClassName=org.h2.Driver

## JPA specific properties
# Creates the schema, destroying previous data.
spring.jpa.hibernate.ddl-auto=create

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

## Database connection pooling properties
# Number of ms to wait before throwing an exception if no connection is available.
spring.datasource.max-wait=10000

# Maximum number of active connections that can be allocated from this pool at the same time.
spring.datasource.tomcat.max-active=10
spring.datasource.tomcat.max-idle=5
spring.datasource.tomcat.min-idle=3

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true


application-test.properties
logging.level.root=WARN
logging.level.org.hibernate=ERROR

spring.datasource.url=jdbc:h2:file:~/db/appTest.db;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;


pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>springTest</groupId>
 <artifactId>springTest</artifactId>
 <version>1</version>


 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.1.6.RELEASE</version>
 </parent>

 <name>springbootApp</name>
 <url>http://maven.apache.org</url>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

 <dependencies>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>


  <dependency>
   <groupId>com.h2database</groupId>
   <artifactId>h2</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>

 </dependencies>
</project>

Test classes are given below.


EmployeeServiceUnitTest.java
package com.sample.app.service;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;

import com.sample.app.dao.impl.EmployeeDaoImpl;
import com.sample.app.model.Employee;
import com.sample.app.service.impl.EmployeeServiceImpl;

@RunWith(MockitoJUnitRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
public class EmployeeServiceUnitTest {

 @Mock
 private EmployeeDaoImpl empDao;

 @InjectMocks
 private EmployeeServiceImpl empService;

 @Before
 public void setup() {
  MockitoAnnotations.initMocks(this);
 }

 @Test
 public void newEmployee() {
  Employee emp1 = new Employee();
  emp1.setId(1);
  emp1.setFirstName("Anil");
  emp1.setLastName("Kumar");

  when(empDao.save(any(Employee.class))).thenReturn(emp1);

  Employee persistedEmployee = empService.save(emp1);

  assertNotNull(persistedEmployee);
  assertNotNull(persistedEmployee.getId());
  assertEquals(emp1.getFirstName(), persistedEmployee.getFirstName());
  assertEquals(emp1.getLastName(), persistedEmployee.getLastName());
 }
}


EmployeeServiceIntegrationTest.java
package com.sample.app.service;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.sample.app.model.Employee;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.NONE)
@ActiveProfiles("test")
public class EmployeeServiceIntegrationTest {
 
 @Autowired
 EmployeeService empService;
 
 @Test
 public void newEmployee() {
  Employee emp1 = new Employee();
  emp1.setFirstName("Anil");
  emp1.setLastName("Kumar");
  
  Employee persistedEmployee = empService.save(emp1);
  
  assertNotNull(persistedEmployee);
  assertNotNull(persistedEmployee.getId());
  assertEquals(emp1.getFirstName(), persistedEmployee.getFirstName());
  assertEquals(emp1.getLastName(), persistedEmployee.getLastName());
 }

}


EmployeeControllerIntegrationTest.java
package com.sample.app.controller;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.sample.app.model.Employee;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
public class EmployeeControllerIntegrationTest {

 @Autowired
 private EmployeeController empController;

 @Test
 public void newEmployee() {
  Employee emp1 = new Employee();
  emp1.setFirstName("Anil");
  emp1.setLastName("Kumar");

  ResponseEntity<Employee> response = empController.save(emp1);

  Employee persistedEmployee = response.getBody();

  assertNotNull(persistedEmployee);
  assertNotNull(persistedEmployee.getId());
  assertEquals(emp1.getFirstName(), persistedEmployee.getFirstName());
  assertEquals(emp1.getLastName(), persistedEmployee.getLastName());
 }

}


Total project structure looks like below.


How to run the test case?

Right click on ‘EmployeeControllerIntegrationTest’, Run As -> Junit Test.

You can download complete working application from this link.



Previous                                                    Next                                                    Home

No comments:

Post a Comment