Categories: springmvc

Spring 4 MVC+Hibernate 4+MySQL+Maven integration + Testing example using annotations

This post shows you how to Unit and integration test your Data layer, service layer and view layer in a Spring 4 MVC + Hibernate 4 + MySQL + Maven integration application.

This post is continuation of Previous post. In this post we will learn how to add unit and integration test in SpringMVC and hibernate based maven project using TestNG, mockito, spring-test, DBUnit & H2 database. To know more about testing with TestNG in general, please refer our TestNG Tutorials. Let’s get going.


Following technologies being used:

  • Spring 4.0.6.RELEASE
  • Hibernate Core 4.3.6.Final
  • validation-api 1.1.0.Final
  • hibernate-validator 5.1.3.Final
  • MySQL Server 5.6
  • Maven 3
  • JDK 1.7
  • Tomcat 8.0.21
  • Eclipse JUNO Service Release 2
  • TestNG 6.9.4
  • Mockito 1.10.19
  • DBUnit 2.2
  • H2 Database 1.4.187

Let’s begin.

Step 1: Adapt directory structure

It’s same directory structure as in previous post. What’s new is that we have added src/test/java & src/test/resources folders and testing artifacts. We will maintain the same package structure in test as in src folder.

Following will be the final project structure:[Note that src/main part is hidden in order to show everything in one image]

Step 2: Review pom.xml

This is same pom.xml as declared in previous post

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

 <modelVersion>4.0.0</modelVersion>
 <groupId>com.websystique.springmvc</groupId>
 <artifactId>SpringHibernateExample</artifactId>
 <packaging>war</packaging>
 <version>1.0.0</version>
 <name>SpringHibernateExample</name>

 <properties>
  <springframework.version>4.0.6.RELEASE</springframework.version>
  <hibernate.version>4.3.6.Final</hibernate.version>
  <mysql.connector.version>5.1.31</mysql.connector.version>
  <joda-time.version>2.3</joda-time.version>
  <testng.version>6.9.4</testng.version>
  <mockito.version>1.10.19</mockito.version>
  <h2.version>1.4.187</h2.version>
  <dbunit.version>2.2</dbunit.version>
 </properties>

 <dependencies>
  <!-- Spring -->
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-tx</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-orm</artifactId>
   <version>${springframework.version}</version>
  </dependency>

  <!-- Hibernate -->
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>${hibernate.version}</version>
  </dependency>

  <!-- jsr303 validation -->
  <dependency>
   <groupId>javax.validation</groupId>
   <artifactId>validation-api</artifactId>
   <version>1.1.0.Final</version>
  </dependency>
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator</artifactId>
   <version>5.1.3.Final</version>
  </dependency>

  <!-- MySQL -->
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>${mysql.connector.version}</version>
  </dependency>

       <!-- Joda-Time -->  
  <dependency>
     <groupId>joda-time</groupId>
     <artifactId>joda-time</artifactId>
     <version>${joda-time.version}</version>
    </dependency>
  
  <!-- To map JodaTime with database type -->    
    <dependency>
      <groupId>org.jadira.usertype</groupId>
      <artifactId>usertype.core</artifactId>
      <version>3.0.0.CR1</version>
  </dependency>

  <!-- Servlet+JSP+JSTL -->
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
  </dependency>
  <dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>javax.servlet.jsp-api</artifactId>
   <version>2.3.1</version>
  </dependency>
  <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
  </dependency>
  
  
  <!-- Testing dependencies -->
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-test</artifactId>
   <version>${springframework.version}</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>org.testng</groupId>
   <artifactId>testng</artifactId>
   <version>${testng.version}</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>org.mockito</groupId>
   <artifactId>mockito-all</artifactId>
   <version>${mockito.version}</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>com.h2database</groupId>
   <artifactId>h2</artifactId>
   <version>${h2.version}</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>dbunit</groupId>
   <artifactId>dbunit</artifactId>
   <version>${dbunit.version}</version>
   <scope>test</scope>
  </dependency>
  
 </dependencies>

 <build>
  <pluginManagement>
   <plugins>
    <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-compiler-plugin</artifactId>
     <version>3.2</version>
     <configuration>
      <source>1.7</source>
      <target>1.7</target>
     </configuration>
    </plugin>
    <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-war-plugin</artifactId>
     <version>2.4</version>
     <configuration>
      <warSourceDirectory>src/main/webapp</warSourceDirectory>
      <warName>SpringHibernateExample</warName>
      <failOnMissingWebXml>false</failOnMissingWebXml>
     </configuration>
    </plugin>
   </plugins>
  </pluginManagement>
  <finalName>SpringHibernateExample</finalName>
 </build>
</project>

Just to recall that dependencies spring-test, testNG, mockito, h2 & DBUnit are all here for Testing purpose only.

Spring-test : We will be using spring-test annotations in our test classes.
TestNG : We will be using TestNG as our testing framework (& it’s my favorite anyway).
Mockito : We would be time to time doing some mocking, like mocking dao when testing service.
DBUnit : We will use DBUnit to mange our data during data/dao layer testing
H2 Database : For database layer, it’s more of integration-test than unit-test. IMO, unit tests does not bring real value while testing data layer. We will be using in-memory H2 database to do our integration-tests.

Let’s Start some real testing.

1) Testing Controllers:

package com.websystique.springmvc.controller;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.joda.time.LocalDate;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import static org.mockito.Mockito.atLeastOnce;

import org.springframework.context.MessageSource;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;


import com.websystique.springmvc.model.Employee;
import com.websystique.springmvc.service.EmployeeService;

public class AppControllerTest {

 @Mock
 EmployeeService service;
 
 @Mock
 MessageSource message;
 
 @InjectMocks
 AppController appController;
 
 @Spy
 List<Employee> employees = new ArrayList<Employee>();

 @Spy
 ModelMap model;
 
 @Mock
 BindingResult result;
 
 @BeforeClass
 public void setUp(){
  MockitoAnnotations.initMocks(this);
  employees = getEmployeeList();
 }
 
 @Test
 public void listEmployees(){
  when(service.findAllEmployees()).thenReturn(employees);
  Assert.assertEquals(appController.listEmployees(model), "allemployees");
  Assert.assertEquals(model.get("employees"), employees);
  verify(service, atLeastOnce()).findAllEmployees();
 }
 
 @Test
 public void newEmployee(){
  Assert.assertEquals(appController.newEmployee(model), "registration");
  Assert.assertNotNull(model.get("employee"));
  Assert.assertFalse((Boolean)model.get("edit"));
  Assert.assertEquals(((Employee)model.get("employee")).getId(), 0);
 }


 @Test
 public void saveEmployeeWithValidationError(){
  when(result.hasErrors()).thenReturn(true);
  doNothing().when(service).saveEmployee(any(Employee.class));
  Assert.assertEquals(appController.saveEmployee(employees.get(0), result, model), "registration");
 }

 @Test
 public void saveEmployeeWithValidationErrorNonUniqueSSN(){
  when(result.hasErrors()).thenReturn(false);
  when(service.isEmployeeSsnUnique(anyInt(), anyString())).thenReturn(false);
  Assert.assertEquals(appController.saveEmployee(employees.get(0), result, model), "registration");
 }

 
 @Test
 public void saveEmployeeWithSuccess(){
  when(result.hasErrors()).thenReturn(false);
  when(service.isEmployeeSsnUnique(anyInt(), anyString())).thenReturn(true);
  doNothing().when(service).saveEmployee(any(Employee.class));
  Assert.assertEquals(appController.saveEmployee(employees.get(0), result, model), "success");
  Assert.assertEquals(model.get("success"), "Employee Axel registered successfully");
 }

 @Test
 public void editEmployee(){
  Employee emp = employees.get(0);
  when(service.findEmployeeBySsn(anyString())).thenReturn(emp);
  Assert.assertEquals(appController.editEmployee(anyString(), model), "registration");
  Assert.assertNotNull(model.get("employee"));
  Assert.assertTrue((Boolean)model.get("edit"));
  Assert.assertEquals(((Employee)model.get("employee")).getId(), 1);
 }

 @Test
 public void updateEmployeeWithValidationError(){
  when(result.hasErrors()).thenReturn(true);
  doNothing().when(service).updateEmployee(any(Employee.class));
  Assert.assertEquals(appController.updateEmployee(employees.get(0), result, model,""), "registration");
 }

 @Test
 public void updateEmployeeWithValidationErrorNonUniqueSSN(){
  when(result.hasErrors()).thenReturn(false);
  when(service.isEmployeeSsnUnique(anyInt(), anyString())).thenReturn(false);
  Assert.assertEquals(appController.updateEmployee(employees.get(0), result, model,""), "registration");
 }

 @Test
 public void updateEmployeeWithSuccess(){
  when(result.hasErrors()).thenReturn(false);
  when(service.isEmployeeSsnUnique(anyInt(), anyString())).thenReturn(true);
  doNothing().when(service).updateEmployee(any(Employee.class));
  Assert.assertEquals(appController.updateEmployee(employees.get(0), result, model, ""), "success");
  Assert.assertEquals(model.get("success"), "Employee Axel updated successfully");
 }
 
 
 @Test
 public void deleteEmployee(){
  doNothing().when(service).deleteEmployeeBySsn(anyString());
  Assert.assertEquals(appController.deleteEmployee("123"), "redirect:/list");
 }

 public List<Employee> getEmployeeList(){
  Employee e1 = new Employee();
  e1.setId(1);
  e1.setName("Axel");
  e1.setJoiningDate(new LocalDate());
  e1.setSalary(new BigDecimal(10000));
  e1.setSsn("XXX111");
  
  Employee e2 = new Employee();
  e2.setId(2);
  e2.setName("Jeremy");
  e2.setJoiningDate(new LocalDate());
  e2.setSalary(new BigDecimal(20000));
  e2.setSsn("XXX222");
  
  employees.add(e1);
  employees.add(e2);
  return employees;
 }
}

Run above test class using TestNG Eclipse Plugin or Maven [mvn clean test e.g.]
Here i used TestNG Eclipse plugin to run this test class.

PASSED: deleteEmployee
PASSED: editEmployee
PASSED: listEmployees
PASSED: newEmployee
PASSED: saveEmployeeWithSuccess
PASSED: saveEmployeeWithValidationError
PASSED: saveEmployeeWithValidationErrorNonUniqueSSN
PASSED: updateEmployeeWithSuccess
PASSED: updateEmployeeWithValidationError
PASSED: updateEmployeeWithValidationErrorNonUniqueSSN

===============================================
    Default test
    Tests run: 10, Failures: 0, Skips: 0
===============================================

Explanation of AppControllerTest class:

If you revisit AppController class in Previous post, you will see that AppController basically depends on EmployeeService , MessageSource, Employee, ModelMap & BindingResult to fullfill all of it’s duties. Each of the AppController method is using only of these objects to do it’s real job.

So in order to test AppController, we would need to provide these dependencies. In our example, we do it using Mockito framework. We provide mock of EmployeeService & MessageSource by applying @Mock annotation on them. We also provide spy objects of ModelMap , BindingResult & Employee by applying @Spy annotations on them.

It’s important to understand that Mockito’s @Mock objects are not real instances, they are just bare-bones of instance created using Class of type. But their main capability is that they can remember all the interactions [operations performed] on them.

@Spy objects are on the other hand real instances, but with additional capabilities of remembering all the interactions [operations performed] on them.

@InjectMocks creates an instance of the class and injects the mocks that are created with the @Mock/@Spy objects in it.

MockitoAnnotations.initMocks(this); initializes objects annotated with Mockito annotations [@Mock, @Spy, @Captor, @InjectMocks]

Make sure to call MockitoAnnotations.initMocks when using Mockito annotations, else those mocks will be useless for your tests.

Annotations @Test & @BeforeClass are TestNG specific annotations.

Assert is the TestNG api for doing assertions on expected result and actual result.

when..then & verify are popular stubbing and verification techniques used in tests to define the behavior and then optionally verifying that behavior was indeed executed.

There are many more. Please refer to TestNG tutorial for in depth details about writing tests using TestNG, mockito and other supportive libraries.

2) Testing Service Layer:

package com.websystique.springmvc.service;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import static org.mockito.Mockito.when;

import org.joda.time.LocalDate;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.websystique.springmvc.dao.EmployeeDao;
import com.websystique.springmvc.model.Employee;

public class EmployeeServiceImplTest {

 @Mock
 EmployeeDao dao;
 
 @InjectMocks
 EmployeeServiceImpl employeeService;
 
 @Spy
 List<Employee> employees = new ArrayList<Employee>();
 
 @BeforeClass
 public void setUp(){
  MockitoAnnotations.initMocks(this);
  employees = getEmployeeList();
 }

 @Test
 public void findById(){
  Employee emp = employees.get(0);
  when(dao.findById(anyInt())).thenReturn(emp);
  Assert.assertEquals(employeeService.findById(emp.getId()),emp);
 }

 @Test
 public void saveEmployee(){
  doNothing().when(dao).saveEmployee(any(Employee.class));
  employeeService.saveEmployee(any(Employee.class));
  verify(dao, atLeastOnce()).saveEmployee(any(Employee.class));
 }
 
 @Test
 public void updateEmployee(){
  Employee emp = employees.get(0);
  when(dao.findById(anyInt())).thenReturn(emp);
  employeeService.updateEmployee(emp);
  verify(dao, atLeastOnce()).findById(anyInt());
 }

 @Test
 public void deleteEmployeeBySsn(){
  doNothing().when(dao).deleteEmployeeBySsn(anyString());
  employeeService.deleteEmployeeBySsn(anyString());
  verify(dao, atLeastOnce()).deleteEmployeeBySsn(anyString());
 }
 
 @Test
 public void findAllEmployees(){
  when(dao.findAllEmployees()).thenReturn(employees);
  Assert.assertEquals(employeeService.findAllEmployees(), employees);
 }
 
 @Test
 public void findEmployeeBySsn(){
  Employee emp = employees.get(0);
  when(dao.findEmployeeBySsn(anyString())).thenReturn(emp);
  Assert.assertEquals(employeeService.findEmployeeBySsn(anyString()), emp);
 }

 @Test
 public void isEmployeeSsnUnique(){
  Employee emp = employees.get(0);
  when(dao.findEmployeeBySsn(anyString())).thenReturn(emp);
  Assert.assertEquals(employeeService.isEmployeeSsnUnique(emp.getId(), emp.getSsn()), true);
 }
 
 
 public List<Employee> getEmployeeList(){
  Employee e1 = new Employee();
  e1.setId(1);
  e1.setName("Axel");
  e1.setJoiningDate(new LocalDate());
  e1.setSalary(new BigDecimal(10000));
  e1.setSsn("XXX111");
  
  Employee e2 = new Employee();
  e2.setId(2);
  e2.setName("Jeremy");
  e2.setJoiningDate(new LocalDate());
  e2.setSalary(new BigDecimal(20000));
  e2.setSsn("XXX222");
  
  employees.add(e1);
  employees.add(e2);
  return employees;
 }
 
}

Run above test class using TestNG Eclipse Plugin or Maven [mvn clean test e.g.]

PASSED: deleteEmployeeBySsn
PASSED: findAllEmployees
PASSED: findById
PASSED: findEmployeeBySsn
PASSED: isEmployeeSsnUnique
PASSED: saveEmployee
PASSED: updateEmployee

===============================================
    Default test
    Tests run: 7, Failures: 0, Skips: 0
===============================================

Explanation of EmployeeServiceImplTest class:

If you revisit EmployeeServiceImpl class in Previous post, you will see that EmployeeServiceImpl basically depends on EmployeeDao & Employee to fulfill all of it’s duties. Each of the EmployeeServiceImplmethod is using only of these objects to do it’s real job.

As explained above, in order to test EmployeeServiceImpl, we would need to provide these dependencies. In our example, we do it using Mockito framework. We provide mock of EmployeeDao by applying @Mock annotation on it. We also provide spy objects of Employee by applying @Spy annotations on them.

@InjectMocks creates an instance of the class and injects the mocks that are created with the @Mock/@Spy objects in it.

MockitoAnnotations.initMocks(this); initializes objects annotated with Mockito annotations [@Mock, @Spy, @Captor, @InjectMocks]

So, Make sure to call MockitoAnnotations.initMocks when using Mockito annotations, else those mocks will be useless for your tests.

Please refer to TestNG tutorial for in depth details about writing tests using TestNG, mockito and other supportive libraries.

3) Testing Data Layer:

Testing DAO or data layer is always a subject of debate. What exactly we want to test? Are we just testing the methods from DAO implementation class and making sure that each and every line of code in those methods is covered?

If we think in terms of unit-test, than our goal becomes testing every line of DAO code while really mocking all the external systems/dependencies. IMO, we can’t truly test a data-layer without really interacting with the database itself. And then it becomes an integration test.

Anyway, we will perform integration-test on our DAO layer to make sure that it works as expected. We will be using in-memory H2 database to do our integration-tests.

If we look back at actual dao/data-layer class EmployeeDaoImpl in Previous post, it relies on hibernate for database interactions. There all hibernate setup related stuff was defined in HibernateConfiguration class. We will need similar setup in tests in order to connect to database and perform hibernate session related operations during our tests.

Below class is a setup class [with Annotations] for all hibernate configuration related activities during tests.

package com.websystique.springmvc.configuration;

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/*
 * This class is same as real HibernateConfiguration class in sources.
 * Only difference is that method dataSource & hibernateProperties 
 * implementations are specific to Hibernate working with H2 database.
 */
@Configuration
@EnableTransactionManagement
@ComponentScan({ "com.websystique.springmvc.dao" })
public class HibernateTestConfiguration {

 @Autowired
 private Environment environment;

 @Bean
 public LocalSessionFactoryBean sessionFactory() {
  LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
  sessionFactory.setDataSource(dataSource());
  sessionFactory.setPackagesToScan(new String[] { "com.websystique.springmvc.model" });
  sessionFactory.setHibernateProperties(hibernateProperties());
  return sessionFactory;
 }

 @Bean(name = "dataSource")
 public DataSource dataSource() {
  DriverManagerDataSource dataSource = new DriverManagerDataSource();
  dataSource.setDriverClassName("org.h2.Driver");
  dataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
  dataSource.setUsername("sa");
  dataSource.setPassword("");
  return dataSource;
 }

 private Properties hibernateProperties() {
  Properties properties = new Properties();
  properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
  properties.put("hibernate.hbm2ddl.auto", "create-drop");
  return properties;
 }

 @Bean
 @Autowired
 public HibernateTransactionManager transactionManager(SessionFactory s) {
  HibernateTransactionManager txManager = new HibernateTransactionManager();
  txManager.setSessionFactory(s);
  return txManager;
 }
}

Above class is exactly same as HibernateConfiguration class defined in src in Previous post. Only difference is that mathods dataSource() & hibernateProperties() are implemented specific to Hibernate & H2 combination. I choose to make a separate test configuration class and not to pollute existing class in Sources with testing related stuff.

It does everything exactly same as the one in Sources folder: it creates a SessionFacoty using a dataSource which is configured to work with in-memory database H2. In order to make hibernate work with H2, we also need to specify the dialect being used [H2 Dialect].

This SessionFactory will be injected in our AbstractDao class defined in Previous post. And from then on, the actual DAO implementation classes [ EmployeeDaoImpl] will use this sessionFactory when running tests against them.

Additionally, we will be using DBUnit to clean-insert sample data in test database[H2] before each test case execution, in order to prepare database before each Dao method execution. This way we make sure that the tests method do not interfere with each other.

Below is a sample class which will act as a base class for all our test classes.

package com.websystique.springmvc.dao;

import javax.sql.DataSource;

import org.dbunit.database.DatabaseDataSourceConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests;
import org.testng.annotations.BeforeMethod;

import com.websystique.springmvc.configuration.HibernateTestConfiguration;


@ContextConfiguration(classes = { HibernateTestConfiguration.class })
public abstract class EntityDaoImplTest extends AbstractTransactionalTestNGSpringContextTests {

 @Autowired
 DataSource dataSource;

 @BeforeMethod
 public void setUp() throws Exception {
  IDatabaseConnection dbConn = new DatabaseDataSourceConnection(
    dataSource);
  DatabaseOperation.CLEAN_INSERT.execute(dbConn, getDataSet());
 }
 
 protected abstract IDataSet getDataSet() throws Exception;

}

AbstractTransactionalTestNGSpringContextTests can (at some extent) be considered as JUnit equivalent of RunWith. This abstract class integrates Spring TestContext support in TestNG environment. It requires a class-level @ContextConfiguration in order to load ApplicationContext using XML configuration files or annotated @Configuration classes.

It also requires a datasource and a transactionManager to be defined in ApplicationContext in order to provide data-access support during testing. We have already defined both datasource & transactionManager in our @Configuration class.

Thanks to transaction support, by default a transaction will be started before each test, and then this transaction will be rolled back at the end of test. You may override the rollback behavior.

Look at setup method annotated with @BeforeMethod. Method annotated with @BeforeMethod is called before each test, so it is an ideal place to do something which is required before each test. In our case , we want the in-memory database to be clean and predefined sample data to be inserted before each test. We will do it right here.

Additionally, for DBUnit to connect to database in order to perform clean-insert, we have to provide a dataSource for it. That’s why we declared a dataSource here, which will be autowired with dataSource defined in HibernateTestConfiguration class.

As shown in above setUp method, firstly we create a connection to database using dataSource available( which will be test dataSource), and execute clean-insert on DB via DBUnit.

Notice the abstract method getDataSet above. This method will be implemented in our tests classes in order to provide the actual test data to be inserted before each test.

Finally, the actual test class which tests methods from our DAO implementation class.

package com.websystique.springmvc.dao;

import java.math.BigDecimal;

import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.Assert;
import org.testng.annotations.Test;

import com.websystique.springmvc.model.Employee;


public class EmployeeDaoImplTest extends EntityDaoImplTest{

 @Autowired
 EmployeeDao employeeDao;

 @Override
 protected IDataSet getDataSet() throws Exception{
  IDataSet dataSet = new FlatXmlDataSet(this.getClass().getClassLoader().getResourceAsStream("Employee.xml"));
  return dataSet;
 }
 
 /* In case you need multiple datasets (mapping different tables) and you do prefer to keep them in separate XML's
 @Override
 protected IDataSet getDataSet() throws Exception {
   IDataSet[] datasets = new IDataSet[] {
     new FlatXmlDataSet(this.getClass().getClassLoader().getResourceAsStream("Employee.xml")),
     new FlatXmlDataSet(this.getClass().getClassLoader().getResourceAsStream("Benefits.xml")),
     new FlatXmlDataSet(this.getClass().getClassLoader().getResourceAsStream("Departements.xml"))
   };
   return new CompositeDataSet(datasets);
 }
 */
 @Test
 public void findById(){
  Assert.assertNotNull(employeeDao.findById(1));
  Assert.assertNull(employeeDao.findById(3));
 }

 
 @Test
 public void saveEmployee(){
  employeeDao.saveEmployee(getSampleEmployee());
  Assert.assertEquals(employeeDao.findAllEmployees().size(), 3);
 }
 
 @Test
 public void deleteEmployeeBySsn(){
  employeeDao.deleteEmployeeBySsn("11111");
  Assert.assertEquals(employeeDao.findAllEmployees().size(), 1);
 }
 
 @Test
 public void deleteEmployeeByInvalidSsn(){
  employeeDao.deleteEmployeeBySsn("23423");
  Assert.assertEquals(employeeDao.findAllEmployees().size(), 2);
 }

 @Test
 public void findAllEmployees(){
  Assert.assertEquals(employeeDao.findAllEmployees().size(), 2);
 }
 
 @Test
 public void findEmployeeBySsn(){
  Assert.assertNotNull(employeeDao.findEmployeeBySsn("11111"));
  Assert.assertNull(employeeDao.findEmployeeBySsn("14545"));
 }

 public Employee getSampleEmployee(){
  Employee employee = new Employee();
  employee.setName("Karen");
  employee.setSsn("12345");
  employee.setSalary(new BigDecimal(10980));
  employee.setJoiningDate(new LocalDate());
  return employee;
 }

}

Below is the content of input file used by DBUnit:

src/test/resources/Employee.xml

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
 <employee id="1" NAME="SAMY" JOINING_DATE="2014-04-16"  SALARY="20000" SSN="11111" />
 <employee id="2" NAME="TOMY" JOINING_DATE="2014-05-17"  SALARY="23000" SSN="11112" />
</dataset>

Run above test class using TestNG Eclipse Plugin or Maven [mvn clean test e.g.]

PASSED: deleteEmployeeByInvalidSsn
PASSED: deleteEmployeeBySsn
PASSED: findAllEmployees
PASSED: findById
PASSED: findEmployeeBySsn
PASSED: saveEmployee

===============================================
    Default test
    Tests run: 6, Failures: 0, Skips: 0
===============================================

Let’s take saveEmployee test case and understand how things happening here.

  • 1) Before any of the test from the classes (which are extending EntityDaoImplTest) starts executing, Spring will load the text context from the configuration classes associated with @ContextConfiguration annotation & create the beans instances defined in those classes, thanks to AbstractTransactionalTestNGSpringContextTests. This will happen only once.
  • 2) During @Bean instance creation, Spring will create the SessionFactory Bean which will be injected with dataSource bean (as defined in HibernateTestConfiguration class) based on database & hibernate properties. Look at the following property
       properties.put("hibernate.hbm2ddl.auto", "create-drop");
    

    Thanks to this hbm2ddl property, when the SessionFactory is created, the schema related to our Model classes will be validated and exported to database. That means Employee table will be created in H2 database.

  • 3) Before the test start, @BeforeMethod will be called, which will instruct DBUnit to connect to database and perform clean-insert.It will insert 2 rows in Employee table (look at Employee.xml content)
  • 4) Now the actual test case saveEmployee is about to start. Just before execution start, a transaction will be started. Method itself will run within this transaction. Once method finished it’s execution, transaction will be rolled back which is default setup. You can override this behavior by annotating the test method with @Rollback(true) annotation. It is defined in [org.springframework.test.annotation.Rollback]
  • 4) Now the actual test case saveEmployee finally starts it’s execution. It will call employeeDao.saveEmployee(getSampleEmployee()); which in-turn will insert the one pre-defined Employee object into H2 database using hibernate. This is the core logic of saveEmployee method anyway. After this operation there will be total 3 rows in Employee table in H2 database. We will assert it for success/failure. Test completes.
  • 5) For next test case, again @BeforeMethod will be called which will delete everything from table and re-insert two rows as defined in Employee.xml. Story continues…
  • 6) When all our tests are done, session will be closed and schema will be dropped.

Shown below is the output of running all the tests using maven [mvn clean test]

E:\workspace7\SpringHibernateExample>mvn clean test
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building SpringHibernateExample 1.0.0
[INFO] ------------------------------------------------------------------------
[WARNING] The artifact dbunit:dbunit:jar:2.2 has been relocated to org.dbunit:dbunit:jar:2.2
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ SpringHibernateExample ---
[INFO] Deleting E:\workspace7\SpringHibernateExample\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ SpringHibernateExample ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 2 resources
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ SpringHibernateExample ---
[WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
[INFO] Compiling 10 source files to E:\workspace7\SpringHibernateExample\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ SpringHibernateExample ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ SpringHibernateExample ---
[WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
[INFO] Compiling 5 source files to E:\workspace7\SpringHibernateExample\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ SpringHibernateExample ---
[INFO] Surefire report directory: E:\workspace7\SpringHibernateExample\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running TestSuite
Configuring TestNG with: org.apache.maven.surefire.testng.conf.TestNG652Configurator@556e7212
Jul 12, 2015 1:46:48 AM org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@8be1456: startup date [Sun Jul 12 01:46:48 CEST 2015]; root of context hierarchy
Jul 12, 2015 1:46:48 AM org.springframework.jdbc.datasource.DriverManagerDataSource setDriverClassName
INFO: Loaded JDBC driver: org.h2.Driver
Jul 12, 2015 1:46:48 AM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
Jul 12, 2015 1:46:48 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.3.6.Final}
Jul 12, 2015 1:46:48 AM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Jul 12, 2015 1:46:48 AM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
Jul 12, 2015 1:46:49 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Jul 12, 2015 1:46:49 AM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
Jul 12, 2015 1:46:49 AM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
Jul 12, 2015 1:46:49 AM org.hibernate.validator.internal.util.Version <clinit>
INFO: HV000001: Hibernate Validator 5.1.3.Final
Jul 12, 2015 1:46:49 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000227: Running hbm2ddl schema export
Jul 12, 2015 1:46:49 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Jul 12, 2015 1:46:49 AM org.springframework.orm.hibernate4.HibernateTransactionManager afterPropertiesSet
INFO: Using DataSource [org.springframework.jdbc.datasource.DriverManagerDataSource@3e2798e6] of Hibernate SessionFactory for HibernateTransactionManager
Jul 12, 2015 1:46:49 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener startNewTransaction
INFO: Began transaction (1) for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique.springmvc.dao.Employee
DaoImplTest@4fc55da3, testMethod = deleteEmployeeByInvalidSsn@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [MergedContextConfigurat
ion@49dc008c testClass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestConfiguration}', contextI
nitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; tra
nsaction manager [org.springframework.orm.hibernate4.HibernateTransactionManager@aa80d36]; rollback [true]
Jul 12, 2015 1:46:50 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener endTransaction
INFO: Rolled back transaction after test execution for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique
.springmvc.dao.EmployeeDaoImplTest@4fc55da3, testMethod = deleteEmployeeByInvalidSsn@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [
MergedContextConfiguration@49dc008c testClass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestCo
nfiguration}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader',
 parent = [null]]]
Jul 12, 2015 1:46:50 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener startNewTransaction
INFO: Began transaction (2) for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique.springmvc.dao.Employee
DaoImplTest@4fc55da3, testMethod = deleteEmployeeBySsn@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@49d
c008c testClass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestConfiguration}', contextInitiali
zerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transactio
n manager [org.springframework.orm.hibernate4.HibernateTransactionManager@aa80d36]; rollback [true]
Jul 12, 2015 1:46:50 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener endTransaction
INFO: Rolled back transaction after test execution for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique
.springmvc.dao.EmployeeDaoImplTest@4fc55da3, testMethod = deleteEmployeeBySsn@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [MergedC
ontextConfiguration@49dc008c testClass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestConfigura
tion}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent
 = [null]]]
Jul 12, 2015 1:46:50 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener startNewTransaction
INFO: Began transaction (3) for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique.springmvc.dao.Employee
DaoImplTest@4fc55da3, testMethod = findAllEmployees@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@49dc00
8c testClass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestConfiguration}', contextInitializer
Classes = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction m
anager [org.springframework.orm.hibernate4.HibernateTransactionManager@aa80d36]; rollback [true]
Jul 12, 2015 1:46:50 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener endTransaction
INFO: Rolled back transaction after test execution for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique
.springmvc.dao.EmployeeDaoImplTest@4fc55da3, testMethod = findAllEmployees@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [MergedCont
extConfiguration@49dc008c testClass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestConfiguratio
n}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent =
[null]]]
Jul 12, 2015 1:46:50 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener startNewTransaction
INFO: Began transaction (4) for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique.springmvc.dao.Employee
DaoImplTest@4fc55da3, testMethod = findById@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@49dc008c testC
lass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestConfiguration}', contextInitializerClasses
= '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [
org.springframework.orm.hibernate4.HibernateTransactionManager@aa80d36]; rollback [true]
Jul 12, 2015 1:46:50 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener endTransaction
INFO: Rolled back transaction after test execution for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique
.springmvc.dao.EmployeeDaoImplTest@4fc55da3, testMethod = findById@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [MergedContextConfi
guration@49dc008c testClass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestConfiguration}', con
textInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]

Jul 12, 2015 1:46:50 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener startNewTransaction
INFO: Began transaction (5) for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique.springmvc.dao.Employee
DaoImplTest@4fc55da3, testMethod = findEmployeeBySsn@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@49dc0
08c testClass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestConfiguration}', contextInitialize
rClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction
manager [org.springframework.orm.hibernate4.HibernateTransactionManager@aa80d36]; rollback [true]
Jul 12, 2015 1:46:50 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener endTransaction
INFO: Rolled back transaction after test execution for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique
.springmvc.dao.EmployeeDaoImplTest@4fc55da3, testMethod = findEmployeeBySsn@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [MergedCon
textConfiguration@49dc008c testClass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestConfigurati
on}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent =
 [null]]]
Jul 12, 2015 1:46:50 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener startNewTransaction
INFO: Began transaction (6) for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique.springmvc.dao.Employee
DaoImplTest@4fc55da3, testMethod = saveEmployee@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@49dc008c t
estClass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestConfiguration}', contextInitializerClas
ses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manag
er [org.springframework.orm.hibernate4.HibernateTransactionManager@aa80d36]; rollback [true]
Jul 12, 2015 1:46:50 AM org.springframework.test.context.transaction.TransactionalTestExecutionListener endTransaction
INFO: Rolled back transaction after test execution for test context [DefaultTestContext@50dcb4b5 testClass = EmployeeDaoImplTest, testInstance = com.websystique
.springmvc.dao.EmployeeDaoImplTest@4fc55da3, testMethod = saveEmployee@EmployeeDaoImplTest, testException = [null], mergedContextConfiguration = [MergedContextC
onfiguration@49dc008c testClass = EmployeeDaoImplTest, locations = '{}', classes = '{class com.websystique.springmvc.configuration.HibernateTestConfiguration}',
 contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [nul
l]]]
Tests run: 23, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.982 sec

Results :

Tests run: 23, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.481s
[INFO] Finished at: Sun Jul 12 01:46:50 CEST 2015
[INFO] Final Memory: 17M/224M
[INFO] ------------------------------------------------------------------------

That’s it.

Download Source Code


References

View Comments

  • Hello,
    First of all thank you very much for the code and explanations. I have a therotical question. I am new to testing. My question is when we test controllers don't we have to test that they add correct messages to the result object. Isn't it a side effect that should be tested?

    Thanks in advance

    • Hi, It's a good approach to test those message as well [instead of mocking them], keeping everything intact in one place. There are times, however, when you are using a service in controller but you really want to test your controller [and not the details of service], mock is the better option there.

  • Hi,
    I have an error, don't org.dbunit.dataset.NoSuchTableException: unv_users

    My HibernateTestConfiguration is:
    @Configuration
    @EnableTransactionManagement
    @ComponentScan({ "com.sfw.core.dao" })
    public class HibernateTestConfiguration {
    @Autowired
    private Environment environment;

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource());
    sessionFactory.setPackagesToScan(new String[] { "com.sfw.core.model" });
    sessionFactory.setHibernateProperties(hibernateProperties());
    return sessionFactory;
    }

    @Bean(name = "dataSource")
    public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("org.h2.Driver");
    dataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;");
    dataSource.setUsername("sa");
    dataSource.setPassword("");
    return dataSource;
    }

    private Properties hibernateProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
    properties.put("hibernate.hbm2ddl.auto", "create");
    properties.put("hibernate.cache.region.factory_class", "org.hibernate.cache.EhCacheRegionFactory");
    return properties;
    }

    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory s) {
    HibernateTransactionManager txManager = new HibernateTransactionManager();
    txManager.setSessionFactory(s);
    return txManager;
    }
    }

    My EntityDAOTest is:

    @ContextConfiguration(classes = { HibernateTestConfiguration.class })
    public abstract class EntityDAOTest extends AbstractTransactionalTestNGSpringContextTests {

    @Autowired
    DataSource dataSource;

    @BeforeMethod
    public void setUp() throws Exception {
    IDatabaseConnection dbConn = new DatabaseDataSourceConnection(dataSource);
    DatabaseOperation.CLEAN_INSERT.execute(dbConn, getDataSet());
    }

    protected abstract IDataSet getDataSet() throws Exception;

    }

    My H2GroupDAOTest is:

    public class H2GroupDAOTest extends EntityDAOTest {

    @Autowired
    IGroupDAO groupDAO;

    @Autowired
    IUserDAO userDAO;

    @Override
    protected IDataSet getDataSet() throws Exception{
    IDataSet dataSet = new FlatXmlDataSet(this.getClass().getClassLoader().getResourceAsStream("test-db/users.xml"));
    return dataSet;
    }

    @Test
    public void getAllTest() {
    List UserList = userDAO.getAll();
    }

    The users.xml ils:

    What am I doing wrong?

    • Hi I don't see any error as such. Do you have your test-db inside src/test/resources ? BTW, your test is not doing anything for the moment, you should use some Assertion.

  • Description Resource Path Location Type
    Cannot change version of project facet Dynamic Web Module to 3.1. SpringHibernateExample line 1 Maven Java EE Configuration Problem

  • For example, if I modify listEmployees function in controller become following:
    public String listEmployees (ModelMap model) {

    List employees= employyService.findAllEmployees();();
    model.addAttribute("employees", employees);
    model.addAttribute("loggedinuser", getPrincipal());
    return "allemployees";
    }

    and the getPrincipal() code is following:
    private String getPrincipal(){
    String userName = null;
    Object principal = getCurrentUser();

    if (principal instanceof UserDetails) {
    userName = ((UserDetails)principal).getUsername();
    } else {
    userName = principal.toString();
    }
    return userName;
    }

    private Object getCurrentUser(){
    return SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }

    Then how can I make the test passed? Because without "model.addAttribute("loggedinuser", getPrincipal());" it actually can make it passed, but if include this line, if will complain Null Pointer Exceptino due to maven cannot get current login user...

  • I have an error in runtime of the test, the next line:
    DatabaseOperation.CLEAN_INSERT.execute(dbConn, getDataSet());

    Error contents:
    org.dbunit.dataset.NoSuchTableException: user
    Contents of variables during debugging are specified in the attached image.

    I so think that it isn't possible to compare data from the user.xml and a h2db.
    More information can be found in my question on stackoverflow: http://stackoverflow.com/questions/36120739/spring-hibernate-testng-and-h2-org-dbunit-dataset-nosuchtableexception-user

    Please help me to solve this problem.

  • thanks for your efforts!
    i think i can advice you some improvement...

    It seems to me this code is wrong: (Boolean)model.get()
    may be would better to do so: Boolean.valueOf((String) model.get() ?

    • Hi Nick,
      Your comments are appreciated. If you feel something can be improved, please feel free to mention it , i will adapt the post.

Share
Published by

Recent Posts

Spring Boot + AngularJS + Spring Data + JPA CRUD App Example

In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…

8 years ago

Spring Boot Rest API Example

Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…

8 years ago

Spring Boot WAR deployment example

Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…

8 years ago

Spring Boot Introduction + hello world example

Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…

8 years ago

Secure Spring REST API using OAuth2

Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…

8 years ago

AngularJS+Spring Security using Basic Authentication

This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…

8 years ago