Use JAVA SQL Parameters and improve your application security

Use parameters in a JAVA SQL Prepared Statement is a good practice for performance reasons but also is good way to improve the security of your application.

Advertisements

Recently I had to do some maintenance tasks in a legacy system. You know, work with code that you didn’t write can be a very interesting experience… or a nightmare…
In this case, I found several issues about code structure, performance and security. But the most important (I think) were related with the queries used by the application: they didn’t use any SQL parameter to perform the select, insert, update and delete operations.

After finish that work I thought “maybe not everybody knows about this, maybe could be a good idea write a sample code”… So, here is a little example about how to use parameters in a JAVA SQL Prepared Statement. Remember: use parameters is a good way, not only to improve the performance (because the statements “are” in the DB cache), also to improve the security of your application.

Of couse, if you know a better solution for one or more cases or you want to share your best practices with us, please, let me know and I will update this post 🙂

Some Notes about Secutiry

  • use POST restful end-points whenever you can
  • return only one object instead a list of objects (for example if you expect the user’s details from a service return an user object instead a list of user objects)
  • validate the input in each method and, if you can, create a common validator class for that
  • check the size the response: if you expect one and only one user’s record, check it before send the response to the client
  • query for the columns of the table instead use *
  • avoid return extra data: if you need user’s name and birth date, only return that
  • avoid hardcode values in your statements: always user SQL parameters
  • avoid store decrypted password in files, tables, etc.
  • avoid return detailed errors to the client: messages with the table name, complete query or expected values for the where clause

Imagine that you have a table with this structure and data:
2017-06-25-Captura-001
And want to create and Restful end-point to get the user’s details.
Also, imagine that you get the data from table without parameters…

Example of Controller Class

package com.example.sample.db.securestmt.controller;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.example.sample.db.securestmt.dto.ExampleDTO;
import com.example.sample.db.securestmt.service.ExampleService;

/**
 * Handles the request for the example. 
 * @author Gabriel
 *
 */
@RestController
public class ExampleController {

	private static final Logger LOGGER = LoggerFactory.getLogger(ExampleController.class);
	
	@Autowired
	ExampleService exampleService;
	
	/**
	 * Gets all configured names.
	 * @return
	 */
	@RequestMapping(path="/user/info", produces= MediaType.APPLICATION_JSON_VALUE)
	public ResponseEntity<?> getUserInfo(@RequestParam final String user) {
		LOGGER.info("getUserInfo - start");
		
		ResponseEntity<?> responseEntity = null;
		
		try{
			List<ExampleDTO> users = exampleService.getUserInfo(user);
			responseEntity = ResponseEntity.ok(users);
		} catch (Exception e) {
			responseEntity = ResponseEntity.badRequest().body("ERROR : " + e.getMessage());
		}
		
		LOGGER.info("getUserInfo - end");
		return responseEntity;		
	}	
}

Example of Service Class

package com.example.sample.db.securestmt.service;

import java.sql.SQLException;
import java.util.List;

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

import com.example.sample.db.securestmt.dao.ExampleDAO;
import com.example.sample.db.securestmt.dto.ExampleDTO;

/**
 * Services for the example.
 * @author Gabriel
 *
 */
@Service
public class ExampleService {
	
	@Autowired
	@Qualifier("NonSecureDAO")
	ExampleDAO exampleDAO;
	
	/**
	 * Gets all configured names.
	 * @return
	 * @throws SQLException
	 */
	public List<ExampleDTO> getUserInfo(final String user) throws SQLException {
		return exampleDAO.findUserInfoByUser(user);
	}
}

Example of Unsecured DAO Class

package com.example.sample.db.securestmt.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.example.sample.db.securestmt.dto.ExampleDTO;

@Repository("NonSecureDAO")
public class ExampleNonSecureDAOImpl implements ExampleDAO {

	private static final Logger LOGGER = LoggerFactory.getLogger(ExampleNonSecureDAOImpl.class);
	
	final static String QUERY_FIND_ALL_UNSECURE = " SELECT * FROM USER_TEST WHERE USER = ";
	
	@Autowired
	DataSource dataSource;
	
	public List<ExampleDTO> findUserInfoByUser(final String user) throws SQLException {
		List<ExampleDTO> records = new ArrayList<>();
		
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		
		try {
			connection = dataSource.getConnection();
			preparedStatement = connection.prepareStatement(QUERY_FIND_ALL_UNSECURE + "'"+ user +"'");
			resultSet = preparedStatement.executeQuery();
			
			while (resultSet.next()) {
				ExampleDTO dto = new ExampleDTO();
				dto.setId(resultSet.getString(1));
				dto.setName(resultSet.getString(2));
				dto.setUser(resultSet.getString(3));
				dto.setPassword(resultSet.getString(4));
				
				records.add(dto);
			}
			
			return records;
		} catch (SQLException sqle) {
			LOGGER.error("Error performing query: " + QUERY_FIND_ALL_UNSECURE, sqle);
			throw sqle;
		} finally {
			closeSQLObject(resultSet, ResultSet.class.getName());
			closeSQLObject(preparedStatement, PreparedStatement.class.getName());
			closeSQLObject(connection, Connection.class.getName());
		}
	}
	
	/**
	 * Closes the given SQL AutoCloseable object.
	 * @param sqlObject
	 * @param sqlObjectType
	 */
	private void closeSQLObject(final AutoCloseable sqlObject, final String sqlObjectType) {
		try {
			sqlObject.close();
		} catch (Exception e) {
			LOGGER.warn("Exception closing : {}", sqlObjectType);
		}
	}
}

In the “happy path” the application or an user should get the user’s details setting the user parameter as user=[User Value]:
2017-06-25-Captura-002

But if someone tries to check if you have a security hole? Maybe could do something like user=’AND (or another non valid SQL syntax) to get an exception:
2017-06-25-Captura-003

And if you or team return detailed exceptions to the client-side, maybe someone could do something worse… like set add an OR clause with a true condition to get the details from all user in the table: user=’ OR ‘ABC’=’ABC’
2017-06-25-Captura-004

Use parameters in your SQL statements can solve this kind of issues quickly:

Example of Secured DAO Class

package com.example.sample.db.securestmt.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.example.sample.db.securestmt.dto.ExampleDTO;

@Repository("SecureDAO")
public class ExampleSecureDAOImpl implements ExampleDAO {

	private static final Logger LOGGER = LoggerFactory.getLogger(ExampleSecureDAOImpl.class);
	
	final static String QUERY_FIND_ALL_SECURE = " SELECT ID, NAME, USER, PASSWORD FROM USER_TEST WHERE USER = ?";
	
	@Autowired
	DataSource dataSource;
	
	public List<ExampleDTO> findUserInfoByUser(final String user) throws SQLException {
		List<ExampleDTO> records = new ArrayList<>();
		
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		
		try {
			connection = dataSource.getConnection();
			preparedStatement = connection.prepareStatement(QUERY_FIND_ALL_SECURE);
			preparedStatement.setString(1, user);
			resultSet = preparedStatement.executeQuery();
			
			while (resultSet.next()) {
				ExampleDTO dto = new ExampleDTO();
				dto.setId(resultSet.getString(1));
				dto.setName(resultSet.getString(2));
				dto.setUser(resultSet.getString(3));
				dto.setPassword(resultSet.getString(4));
				
				records.add(dto);
			}
			
			return records;
		} catch (SQLException sqle) {
			LOGGER.error("Error performing query. Please contact the User Support Service", sqle);
			throw sqle;
		} finally {
			closeSQLObject(resultSet, ResultSet.class.getName());
			closeSQLObject(preparedStatement, PreparedStatement.class.getName());
			closeSQLObject(connection, Connection.class.getName());
		}
	}
	
	/**
	 * Closes the given SQL AutoCloseable object.
	 * @param sqlObject
	 * @param sqlObjectType
	 */
	private void closeSQLObject(final AutoCloseable sqlObject, final String sqlObjectType) {
		try {
			sqlObject.close();
		} catch (Exception e) {
			LOGGER.warn("Exception closing : {}", sqlObjectType);
		}
	}
}

Final notes
Remember: use parameters in your SQL statements can avoid security issues and also improve the performance of your application… and are easier to develop and maintain that the “hardcoded” where conditions! 🙂

You can get the complete code from my public GitHub repository:
https://github.com/Gabotto/SampleDBSecureStatements

Let me know if you have any problem, comment or new ideas:
WordPress: https://gabelopment.wordpress.com/
Email: gabelopment@gmail.com

Also you can find me at Upwork

See you soon with more development notes…

JAVA Unit Test for Spring Boot with Mockito and EasyMock

Here they are some ideas about testing using the different tools given by Spring Boot Test dependency. For me and my team they are so useful when we write and run the Unit Test for medium or high complexity classes.

Here they are some ideas about testing using the different tools given by Spring Boot Test dependency. Maybe some tips are not consider as the best practices by the Spring Boot, Mockito, EasyMock and/or TDD folllowers but for me and my team they are so useful when we write and run the Unit Test for medium or high complexity classes.
If you found a better solution for one or more cases or you want to share your best practices with us, please, let me know and I will update this post :).

Add the Maven dependencies

Add the Spring Boot starter test dependency to your pom.xml

		<!--  junit test with mockito -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

If you prefer to use EasyMock as the Unit Test framework, add the this dependency to your pom.xml

		<!-- junit test with easymock -->
		<dependency>
		    <groupId>org.easymock</groupId>
		    <artifactId>easymock</artifactId>
		    <version>3.4</version>
			<scope>test</scope>
		</dependency>

If you need to mock some environment variables or system properties in your Unit Test cases you can use the “system-rules” dependency:

		<!-- mocking environment variables -->
		<dependency>
			<groupId>com.github.stefanbirkner</groupId>
			<artifactId>system-rules</artifactId>
			<version>1.16.0</version>
			<scope>test</scope>
		</dependency>

Some Notes for Spring Boot
Spring Boot provides a number of utilities and annotations to help you when you are testing your application.
Test support is provided by two modules: spring-boot-test contains core items and spring-boot-test-autoconfigure supports auto-configuration for tests.
The ‘Starter’ dependency imports both Spring Boot test modules as well has JUnit, AssertJ, Hamcrest and a number of other useful libraries:

  • JUnit: The standard for unit testing Java applications
  • Spring Test & Spring Boot Test: Utilities and integration test support for Spring Boot applications
  • AssertJ: A fluent assertion library
  • Hamcrest: A library of matcher objects (also known as constraints or predicates)
  • Mockito: A Java mocking framework
  • JSONassert: An assertion library for JSON
  • JsonPath: XPath for JSON

Tips for Spring Boot 1.4.1.RELEASE or higher

  • @RunWith(SpringRunner.class): Use this annotation to invoke the Spring’s runner version 1.4 in Spring Boot Test and common JUnit tests
  • @SpringBootTest: Annotation that creates the Spring Application Context and runs the servlet container. Useful for integration test but too complex for simple JUnit test cases
  • @MockBean: Creates an instance of Bean mocking all their methods. You can define/change behaviors using Mockito’s clauses
  • @SpyBean: Creates an instance of Bean that invokes to their real methods, except you define particular behaviors using Mockito’s clauses

Tips for Spring Boot 1.3.8.RELEASE or lower

  • As Spring Boot uses a previous version of Mockito framewrok, you don’t have the @RunWith, @SpringBootTest, @MockBean and @SpyBean annotations

General tips for Mockito, JUnit and Hamcrest

  • Mock: Creates an instance of the class mocking all their methods. You can define/change behaviors using Mockito’s clauses (for example doXXX, when or given)
  • Spy: Creates an instance of the class that invokes to their real methods, except you define particular behaviors using Mockito’s clauses (for example doXXX, when or given)
  • WhiteBox: Part of Mockito. Useful to set values to private fields by reflection (probably is not a good TDD practice)
  • doReturn/when clause: Set expected return value for a mock instance when invoke a method. In some cases works instead of when or give clauses
  • doThrow/when clause: Set expected thrown exception for a mock instance when invoke a method
  • doNothing/when clause: Set expected no action for a mock instance when invoke a method. Useful for mock void methods
  • doXXX: You can chain expected results for more than one interaction: doReturn(first interction expected result).doReturn(second interaction expected result).when…
  • AnyXXX: Applies the behavior to any parameter do you use in the mock object
  • Verify: Used to verify the invocation of the mock, the number of interactions (or no interactions) with the mock (or a specific method), the order of interactions, if an interaction has occurred at least certain number of times, the arguments of the interaction, etc
  • @InjectMocks: Inject mocks only either by constructor injection, setter injection, or property injection in order. Useful for Spring Boot versions lower than 1.4
  • Use @Rule and ExpectedException to test the expected exceptions. Important: you have to define as public field in your test class
  • The Hamcrest matchers assertThat, equalTo, notNullValue are easy to use and very descriptive
  • Use @Before annotation for your setUp method (will be executed before each test method execution in your class)
  • Use @After annotation for your tearDown method (will be executed after each test method execution in your class)
  • If you need to mock system properties, system environment variables or other java.lang system features, you could use system-rules dependency

Example – Test a Spring Boot Controller

Controller Class

package com.example.sample.unit.test.SampleUnitTestsSB_141.controller;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.sample.unit.test.SampleUnitTestsSB_141.service.ExampleService;

/**
 * Handles the request for the example. 
 * @author Gabriel
 *
 */
@RestController
public class ExampleController {

	private static final Logger LOGGER = LoggerFactory.getLogger(ExampleController.class);
	
	@Autowired
	ExampleService exampleService;
	
	/**
	 * Gets all configured names.
	 * @return
	 */
	@RequestMapping(path="/test/get", produces= MediaType.APPLICATION_JSON_VALUE)
	public ResponseEntity<Map<String,String>> getAllNames() {
		LOGGER.info("getAllNames - start");
		ResponseEntity<Map<String,String>> responseEntity = null;
		
		try{
			Map<String,String> allNames = exampleService.getAllNames();
			responseEntity = new ResponseEntity<Map<String,String>>(allNames, HttpStatus.OK);
		} catch (Exception e) {
			Map<String,String> error = new HashMap<>();
			error.put("ERROR", e.getMessage());
			responseEntity = new ResponseEntity<Map<String,String>>(error, HttpStatus.BAD_REQUEST);
		}
		
		LOGGER.info("getAllNames - end");
		return responseEntity;		
	}	

}

Unit Test for the Controller Class using Mockito (with Spring Boot 1.4.1.RELEASE or higher)

package com.example.sample.unit.test.SampleUnitTestsSB_141.controller.mockito;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

import com.example.sample.unit.test.SampleUnitTestsSB_141.controller.ExampleController;
import com.example.sample.unit.test.SampleUnitTestsSB_141.service.ExampleService;

import static org.hamcrest.MatcherAssert.assertThat;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.equalTo;

@RunWith(SpringRunner.class) // since 1.4.X version we can use this annotation to run the test using SB features
public class ExampleControllerTest {

	@Rule
	public ExpectedException thrown = ExpectedException.none();
	
	// SpyBean instantiates the subject of test, injects the mocked dependencies and invokes the real object methods
	@SpyBean
	private ExampleController exampleController;
	
	// mock the autowired dependency of the test subject		
	@MockBean
	ExampleService exampleServiceMock;
	
	// expect values to be returned by the controller
	private Map<String,String> expectedNames;
	
	// executed before each test case method -> initializes the expected values
	@Before
	public void setUp() {
		expectedNames = new HashMap<>();
		
		for (int i = 1; i < 6; i++) {
			expectedNames.put(String.valueOf(i), "Name "+ i);
		}
		
		// we don't need initializes the mocked objects and their dependencies -> Spring Boot doing that 🙂 
		// MockitoAnnotations.initMocks(this);
	}
	
	@Test
	public void getAllNamesWithValidArgumentsShouldReturnAResponseEntityWithMapOfNamesAndHttpStatusOK() throws Exception {
		// you can use in static way or do a static import
		Mockito.doReturn(expectedNames).when(exampleServiceMock).getAllNames();
		
		// invokes the test subject that uses the mocked behaviors		
		ResponseEntity<Map<String,String>> result = exampleController.getAllNames();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.getStatusCode(), equalTo(HttpStatus.OK));
		assertThat(result.getBody(), notNullValue());
		assertThat(result.getBody().size(), equalTo(expectedNames.size()));
		assertThat(result.getBody().get("1"), equalTo(expectedNames.get("1"))); // should be "Name 1"
		assertThat(result.getBody().get("1"), equalTo("Name 1")); // another way for the previous assertion
		assertThat(result.getBody().get("2"), equalTo(expectedNames.get("2")));
		assertThat(result.getBody().get("3"), equalTo(expectedNames.get("3")));
		assertThat(result.getBody().get("4"), equalTo(expectedNames.get("4")));
		assertThat(result.getBody().get("5"), equalTo(expectedNames.get("5")));
		
		// indicates to Mockito that verifies if the mocked objects were called
		Mockito.verify(exampleServiceMock).getAllNames();
	}
	
	@Test
	public void getAllNamesWithValidArgumentsShouldReturnAResponseEntityWithErrorAndHttpStatusBadRequestWhenExampleServiceFails() throws Exception {
		SQLException expectedException = new SQLException("Some Expected Exception");
		
		// forces to throw an exception from the service to test the controller's catch code
		Mockito.doThrow(expectedException).when(exampleServiceMock).getAllNames();
		
		// invokes the test subject that uses the mocked behaviors		
		ResponseEntity<Map<String,String>> result = exampleController.getAllNames();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
		assertThat(result.getBody(), notNullValue());
		assertThat(result.getBody().size(), equalTo(1));
		// should be the message of the service exception
		assertThat(result.getBody().get("ERROR"), equalTo(expectedException.getMessage()));

		Mockito.verify(exampleServiceMock).getAllNames();		
	}
}

Unit Test for the Controller Class using Spring Boot MVC Test feature (with Spring Boot 1.4.1.RELEASE or higher)

package com.example.sample.unit.test.SampleUnitTestsSB_141.controller.mvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import com.example.sample.unit.test.SampleUnitTestsSB_141.controller.ExampleController;
import com.example.sample.unit.test.SampleUnitTestsSB_141.service.ExampleService;

import net.minidev.json.JSONObject;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

@RunWith(SpringRunner.class) // since 1.4.X version we can use this annotation to run the test using SB features
@WebMvcTest(ExampleController.class) // performs a mvc unit test using the SB context (you can configure one for test purpose)
public class ExampleControllerTest {

	// Spring Boot class to perform restful operations
	@Autowired
	private MockMvc mockMVC;
	 
	// mock the autowired dependency of the test subject		
	@MockBean
	ExampleService exampleServiceMock;

	// expect values to be returned by the controller
	private Map<String,String> expectedNames;
	
	// executed before each test case method -> initializes the expected values
	@Before
	public void setUp() {
		expectedNames = new HashMap<>();
		
		for (int i = 1; i < 6; i++) {
			expectedNames.put(String.valueOf(i), "Name "+ i);
		}
	}
	
	@Test
	public void getAllNamesWithValidArgumentsShouldReturnAResponseEntityWithMapOfNamesAndHttpStatusOK() throws Exception {
		// you can use in static way or do a static import
		// mocks the DAO behavior to return the expected names list
		Mockito.doReturn(expectedNames).when(exampleServiceMock).getAllNames();

		this.mockMVC.perform(get("/test/get"))
				.andExpect(status().isOk())
	            .andExpect(content().string(new JSONObject(expectedNames).toJSONString()));

		// indicates to Mockito that verifies if the mocked objects were called
		Mockito.verify(exampleServiceMock).getAllNames();
	}

	@Test
	public void getAllNamesWithValidArgumentsShouldReturnAResponseEntityWithErrorAndHttpStatusBadRequestWhenExampleServiceFails() throws Exception {		
		// forces to throw an exception from the service to test the controller's catch block
		SQLException expectedException = new SQLException("Some Expected Exception");
		Mockito.doThrow(expectedException).when(exampleServiceMock).getAllNames();

		this.mockMVC.perform(get("/test/get"))
				.andExpect(status().isBadRequest())
	            .andExpect(content().string("{\"ERROR\":\"" +expectedException.getMessage()+ "\"}"));

		Mockito.verify(exampleServiceMock).getAllNames();		
	}
}

Unit Test for the Controller Class using Mockito (with Spring Boot 1.3.8.RELEASE or lower)

package com.example.sample.unit.test.SampleUnitTestsSB_138.controller.mockito;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import com.example.sample.unit.test.SampleUnitTestsSB_138.controller.ExampleController;
import com.example.sample.unit.test.SampleUnitTestsSB_138.service.ExampleService;

import static org.hamcrest.MatcherAssert.assertThat;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.equalTo;

// we don't have the @RunWith(SpringRunner.class) annotation -> we use the pure Mockito annotations
public class ExampleControllerTest {

	@Rule
	public ExpectedException thrown = ExpectedException.none();
	
	// instantiates the subject of test and injects the mocked dependencies
	@InjectMocks // use to inject mocked objects in spring boot versions lower than 1.4
	private ExampleController exampleController;
	
	// mock the autowired dependency of the test subject	
	// we don't have the @MockBean in spring boot versions lower than 1.4 -> we use @Mock
	@Mock
	ExampleService exampleServiceMock;
	
	// expect values to be returned by the controller
	private Map<String,String> expectedNames;
	
	// executed before each test case method -> initializes the expected values
	@Before
	public void setUp() {
		expectedNames = new HashMap<>();
		
		for (int i = 1; i < 6; i++) {
			expectedNames.put(String.valueOf(i), "Name "+ i);
		}
		
		// initializes the mocked objects and injects the mocks to the object with @InjectMocks 
		MockitoAnnotations.initMocks(this);
	}
	
	@Test
	public void getAllNamesWithValidArgumentsShouldReturnAResponseEntityWithMapOfNamesAndHttpStatusOK() throws Exception {
		// you can use in static way or do a static import
		Mockito.doReturn(expectedNames).when(exampleServiceMock).getAllNames();
		
		// invokes the test subject that uses the mocked behaviors		
		ResponseEntity<Map<String,String>> result = exampleController.getAllNames();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.getStatusCode(), equalTo(HttpStatus.OK));
		assertThat(result.getBody(), notNullValue());
		assertThat(result.getBody().size(), equalTo(expectedNames.size()));
		assertThat(result.getBody().get("1"), equalTo(expectedNames.get("1"))); // should be "Name 1"
		assertThat(result.getBody().get("1"), equalTo("Name 1")); // another way for the previous assertion
		assertThat(result.getBody().get("2"), equalTo(expectedNames.get("2")));
		assertThat(result.getBody().get("3"), equalTo(expectedNames.get("3")));
		assertThat(result.getBody().get("4"), equalTo(expectedNames.get("4")));
		assertThat(result.getBody().get("5"), equalTo(expectedNames.get("5")));
		
		// indicates to Mockito that verifies if the mocked objects were called
		Mockito.verify(exampleServiceMock).getAllNames();
	}
	
	@Test
	public void getAllNamesWithValidArgumentsShouldReturnAResponseEntityWithErrorAndHttpStatusBadRequestWhenExampleServiceFails() throws Exception {
		SQLException expectedException = new SQLException("Some Expected Exception");
		
		// forces to throw an exception from the service to test the controller's catch code
		Mockito.doThrow(expectedException).when(exampleServiceMock).getAllNames();
		
		// invokes the test subject that uses the mocked behaviors		
		ResponseEntity<Map<String,String>> result = exampleController.getAllNames();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
		assertThat(result.getBody(), notNullValue());
		assertThat(result.getBody().size(), equalTo(1));
		// should be the message of the service exception
		assertThat(result.getBody().get("ERROR"), equalTo(expectedException.getMessage()));

		Mockito.verify(exampleServiceMock).getAllNames();		
	}
}

Unit Test for the Controller Class using EasyMock

package com.example.sample.unit.test.SampleUnitTestsSB_141.controller.easymock;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.easymock.EasyMock;
import org.easymock.EasyMockRunner;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import com.example.sample.unit.test.SampleUnitTestsSB_141.controller.ExampleController;
import com.example.sample.unit.test.SampleUnitTestsSB_141.service.ExampleService;

@RunWith(EasyMockRunner.class)
public class ExampleControllerTest {

	// instantiates the subject of test and injects the mocked dependencies
	@TestSubject
	ExampleController exampleController = new ExampleController();
	
	// mock the autowired dependency of the test subject
	@Mock
	ExampleService exampleServiceMock;
	
	// expect values to be returned by the controller
	private Map<String,String> expectedNames;
	
	// executed before each test case method -> initializes the expected values
	@Before
	public void setUp() {
		expectedNames = new HashMap<>();
		
		for (int i = 1; i < 6; i++) {
			expectedNames.put(String.valueOf(i), "Name "+ i);
		}
	}
	
	@Test
	public void getAllNamesWithValidArgumentsShouldReturnAResponseEntityWithMapOfNamesAndHttpStatusOK() throws Exception {
		// you can use in static way or do a static import
		// mocks the expected behavior for the service in this test case
		// important: you will test only the logic and the coverage of the test subject so mock the dependecies for that
		EasyMock.expect(exampleServiceMock.getAllNames()).andReturn(expectedNames);
		// indicates to EasyMock that has to "record" the expected behavior of mock objects
		EasyMock.replay(exampleServiceMock);
		
		// invokes the test subject that uses the mocked behaviors		
		ResponseEntity<Map<String,String>> result = exampleController.getAllNames();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.getStatusCode(), equalTo(HttpStatus.OK));
		assertThat(result.getBody(), notNullValue());
		assertThat(result.getBody().size(), equalTo(expectedNames.size()));
		assertThat(result.getBody().get("1"), equalTo(expectedNames.get("1"))); // should be "Name 1"
		assertThat(result.getBody().get("1"), equalTo("Name 1")); // another way for the previous assertion
		assertThat(result.getBody().get("2"), equalTo(expectedNames.get("2")));
		assertThat(result.getBody().get("3"), equalTo(expectedNames.get("3")));
		assertThat(result.getBody().get("4"), equalTo(expectedNames.get("4")));
		assertThat(result.getBody().get("5"), equalTo(expectedNames.get("5")));
		
		// indicates to EasyMock that verifies if the mocked objects were called
		EasyMock.verify(exampleServiceMock);
	}

	@Test
	public void getAllNamesWithValidArgumentsShouldReturnAResponseEntityWithErrorAndHttpStatusBadRequestWhenExampleServiceFails() throws Exception {
		SQLException expectedException = new SQLException("Some Expected Exception");
		
		// forces to throw an exception from the service to test the controller's catch code
		EasyMock.expect(exampleServiceMock.getAllNames()).andThrow(expectedException);
		EasyMock.replay(exampleServiceMock);
		
		// invokes the test subject that uses the mocked behaviors		
		ResponseEntity<Map<String,String>> result = exampleController.getAllNames();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
		assertThat(result.getBody(), notNullValue());
		assertThat(result.getBody().size(), equalTo(1));
		// should be the message of the service exception
		assertThat(result.getBody().get("ERROR"), equalTo(expectedException.getMessage()));

		EasyMock.verify(exampleServiceMock);
	}	
}

Example – Test a Spring Boot Service

Service Class

package com.example.sample.unit.test.SampleUnitTestsSB_141.service;

import java.sql.SQLException;
import java.util.Map;

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

import com.example.sample.unit.test.SampleUnitTestsSB_141.dao.ExampleDAO;

/**
 * Services for the example.
 * @author Gabriel
 *
 */
@Service
public class ExampleService {
	
	@Autowired
	ExampleDAO exampleDAO;
	
	/**
	 * Gets all configured names.
	 * @return
	 * @throws SQLException
	 */
	public Map<String,String> getAllNames() throws SQLException {
		return exampleDAO.findAll();
	}
}

Unit Test for the Service Class using Mockito (with Spring Boot 1.4.1.RELEASE or higher)

package com.example.sample.unit.test.SampleUnitTestsSB_141.service.mockito;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.junit4.SpringRunner;

import com.example.sample.unit.test.SampleUnitTestsSB_141.dao.ExampleDAO;
import com.example.sample.unit.test.SampleUnitTestsSB_141.service.ExampleService;

import static org.hamcrest.MatcherAssert.assertThat;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.equalTo;

@RunWith(SpringRunner.class) // since 1.4.X version we can use this annotation to run the test using SB features
public class ExampleServiceTest {

	@Rule
	public ExpectedException thrown = ExpectedException.none();
	
	// SpyBean instantiates the subject of test, injects the mocked dependencies and invokes the real object methods
	@SpyBean
	private ExampleService exampleService;
	
	// mock the autowired dependency of the test subject		
	@MockBean
	ExampleDAO exampleDAOMock;
	
	// expect values to be returned by the service
	private Map<String,String> expectedNames;
	
	// executed before each test case method -> initializes the expected values
	@Before
	public void setUp() {
		expectedNames = new HashMap<>();
		
		for (int i = 1; i < 6; i++) {
			expectedNames.put(String.valueOf(i), "Name "+ i);
		}
		
		// we don't need initializes the mocked objects and their dependencies -> Spring Boot doing that 🙂 
		// MockitoAnnotations.initMocks(this);
	}
	
	@Test
	public void getAllNamesWithValidArgumentsShouldReturnAMapWithAllNames() throws Exception {
		// you can use in static way or do a static import
		Mockito.doReturn(expectedNames).when(exampleDAOMock).findAll();
		
		// invokes the test subject that uses the mocked behaviors		
		Map<String,String> result = exampleService.getAllNames();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.size(), equalTo(expectedNames.size()));
		assertThat(result.get("1"), equalTo(expectedNames.get("1"))); // should be "Name 1"
		assertThat(result.get("1"), equalTo("Name 1")); // another way for the previous assertion
		assertThat(result.get("2"), equalTo(expectedNames.get("2")));
		assertThat(result.get("3"), equalTo(expectedNames.get("3")));
		assertThat(result.get("4"), equalTo(expectedNames.get("4")));
		assertThat(result.get("5"), equalTo(expectedNames.get("5")));
		
		// indicates to Mockito that verifies if the mocked objects were called
		Mockito.verify(exampleDAOMock).findAll();
	}
	
	@Test
	public void getAllNamesWithValidArgumentsShouldThrowASQLExceptionWhenDAOThrowsAnSQLException() throws Exception {
		SQLException expectedException = new SQLException("Some Expected DAO Exception");
		
		// should be before the test subject method invocation
		// indicates that the test case expects an exception of SQLException class with this message
		thrown.expect(SQLException.class);
		thrown.expectMessage(expectedException.getMessage());
								
		// forces to throw an exception from the service to test the controller's catch code
		Mockito.doThrow(expectedException).when(exampleDAOMock).findAll();
		
		// invokes the test subject that uses the mocked behaviors		
		// don't expect any assert because the service method should thrown an Exception
		exampleService.getAllNames();
				
		Mockito.verify(exampleDAOMock).findAll();		
	}
}

Unit Test for the Service Class using Mockito (with Spring Boot 1.3.8.RELEASE or lower)

package com.example.sample.unit.test.SampleUnitTestsSB_138.service.mockito;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import com.example.sample.unit.test.SampleUnitTestsSB_138.dao.ExampleDAO;
import com.example.sample.unit.test.SampleUnitTestsSB_138.service.ExampleService;

import static org.hamcrest.MatcherAssert.assertThat;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.equalTo;

// we don't have the @RunWith(SpringRunner.class) annotation -> we use the pure Mockito annotations
public class ExampleServiceTest {

	@Rule
	public ExpectedException thrown = ExpectedException.none();
	
	// instantiates the subject of test and injects the mocked dependencies
	@InjectMocks // use to inject mocked objects in spring boot versions lower than 1.4
	private ExampleService exampleService;
	
	// mock the autowired dependency of the test subject	
	// we don't have the @MockBean in spring boot versions lower than 1.4 -> we use @Mock
	@Mock
	ExampleDAO exampleDAOMock;
	
	// expect values to be returned by the service
	private Map<String,String> expectedNames;
	
	// executed before each test case method -> initializes the expected values
	@Before
	public void setUp() {
		expectedNames = new HashMap<>();
		
		for (int i = 1; i < 6; i++) {
			expectedNames.put(String.valueOf(i), "Name "+ i);
		}
		
		// initializes the mocked objects and injects the mocks to the object with @InjectMocks 
		MockitoAnnotations.initMocks(this);
	}
	
	@Test
	public void getAllNamesWithValidArgumentsShouldReturnAMapWithAllNames() throws Exception {
		// you can use in static way or do a static import
		Mockito.doReturn(expectedNames).when(exampleDAOMock).findAll();
		
		// invokes the test subject that uses the mocked behaviors		
		Map<String,String> result = exampleService.getAllNames();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.size(), equalTo(expectedNames.size()));
		assertThat(result.get("1"), equalTo(expectedNames.get("1"))); // should be "Name 1"
		assertThat(result.get("1"), equalTo("Name 1")); // another way for the previous assertion
		assertThat(result.get("2"), equalTo(expectedNames.get("2")));
		assertThat(result.get("3"), equalTo(expectedNames.get("3")));
		assertThat(result.get("4"), equalTo(expectedNames.get("4")));
		assertThat(result.get("5"), equalTo(expectedNames.get("5")));
		
		// indicates to Mockito that verifies if the mocked objects were called
		Mockito.verify(exampleDAOMock).findAll();
	}
	
	@Test
	public void getAllNamesWithValidArgumentsShouldThrowASQLExceptionWhenDAOThrowsAnSQLException() throws Exception {
		SQLException expectedException = new SQLException("Some Expected DAO Exception");
		
		// should be before the test subject method invocation
		// indicates that the test case expects an exception of SQLException class with this message
		thrown.expect(SQLException.class);
		thrown.expectMessage(expectedException.getMessage());
								
		// forces to throw an exception from the service to test the controller's catch code
		Mockito.doThrow(expectedException).when(exampleDAOMock).findAll();
		
		// invokes the test subject that uses the mocked behaviors		
		// don't expect any assert because the service method should thrown an Exception
		exampleService.getAllNames();
				
		Mockito.verify(exampleDAOMock).findAll();		
	}
}

Unit Test for the Service Class using EasyMock

package com.example.sample.unit.test.SampleUnitTestsSB_141.service.easymock;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.easymock.EasyMock;
import org.easymock.EasyMockRunner;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;

import com.example.sample.unit.test.SampleUnitTestsSB_141.dao.ExampleDAO;
import com.example.sample.unit.test.SampleUnitTestsSB_141.service.ExampleService;

@RunWith(EasyMockRunner.class)
public class ExampleServiceTest {
	
	// instantiates the subject of test and injects the mocked dependencies
	@TestSubject
	ExampleService exampleService = new ExampleService();
	
	// mock the autowired dependency of the test subject
	@Mock
	ExampleDAO exampleDAOMock;

	// used to assert and catch the expected exceptions thrown by the test subject
	@Rule
	public ExpectedException thrown = ExpectedException.none();
	
	// expect values to be returned by the service
	private Map<String,String> expectedNames;
	
	// executed before each test case method -> initializes the expected values
	@Before
	public void setUp() {
		expectedNames = new HashMap<>();
		
		for (int i = 1; i < 6; i++) {
			expectedNames.put(String.valueOf(i), "Name "+ i);
		}
	}
	
	@Test
	public void getAllNamesWithValidArgumentsShouldReturnAMapWithAllNames() throws Exception {
		// you can use in static way or do a static import
		// mocks the expected behavior for the DAO in this test case
		// important: you will test only the logic and the coverage of the test subject so mock the dependecies for that
		EasyMock.expect(exampleDAOMock.findAll()).andReturn(expectedNames);
		// indicates to EasyMock that has to "record" the expected behavior of mock objects
		EasyMock.replay(exampleDAOMock);
		
		// invokes the test subject that uses the mocked behaviors		
		Map<String,String> result = exampleService.getAllNames();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.size(), equalTo(expectedNames.size()));
		assertThat(result.get("1"), equalTo(expectedNames.get("1"))); // should be "Name 1"
		assertThat(result.get("1"), equalTo("Name 1")); // another way for the previous assertion
		assertThat(result.get("2"), equalTo(expectedNames.get("2")));
		assertThat(result.get("3"), equalTo(expectedNames.get("3")));
		assertThat(result.get("4"), equalTo(expectedNames.get("4")));
		assertThat(result.get("5"), equalTo(expectedNames.get("5")));
		
		// indicates to EasyMock that verifies if the mocked objects were called
		EasyMock.verify(exampleDAOMock);
	}

	@Test
	public void getAllNamesWithValidArgumentsShouldThrowASQLExceptionWhenDAOThrowsAnSQLException() throws Exception {
		SQLException expectedException = new SQLException("Some Expected DAO Exception");

		// should be before the test subject method invocation
		// indicates that the test case expects an exception of SQLException class with this message
		thrown.expect(SQLException.class);
		thrown.expectMessage(expectedException.getMessage());
				
		// forces to throw an exception from the service to test the controller's catch code
		EasyMock.expect(exampleDAOMock.findAll()).andThrow(expectedException);
		EasyMock.replay(exampleDAOMock);
		
		// invokes the test subject that uses the mocked behaviors		
		// don't expect any assert because the service method should thrown an Exception
		exampleService.getAllNames();
				
		EasyMock.verify(exampleDAOMock);
	}	
}

Example – Test a Spring Boot JDBC DAO

DAO Class

package com.example.sample.unit.test.SampleUnitTestsSB_141.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class ExampleDAOImpl implements ExampleDAO {

	private static final Logger LOGGER = LoggerFactory.getLogger(ExampleDAOImpl.class);
	
	final static String QUERY_FIND_ALL = " SELECT * FROM TEST ";
	
	@Autowired
	DataSource dataSource;
	
	public Map<String,String> findAll() throws SQLException {
		Map<String,String> records = new HashMap<>();
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		
		try {
			connection = dataSource.getConnection();
			preparedStatement = connection.prepareStatement(QUERY_FIND_ALL);
			resultSet = preparedStatement.executeQuery();
			
			while (resultSet.next()) {
				records.put(resultSet.getString(1), resultSet.getString(2));
			}
			
			return records;
		} catch (SQLException sqle) {
			LOGGER.error("Error performing query", sqle);
			throw sqle;
		} finally {
			closeSQLObject(resultSet, ResultSet.class.getName());
			closeSQLObject(preparedStatement, PreparedStatement.class.getName());
			closeSQLObject(connection, Connection.class.getName());
		}
	}
	
	/**
	 * Closes the given SQL AutoCloseable object.
	 * @param sqlObject
	 * @param sqlObjectType
	 */
	private void closeSQLObject(final AutoCloseable sqlObject, final String sqlObjectType) {
		try {
			sqlObject.close();
		} catch (Exception e) {
			LOGGER.warn("Exception closing : {}", sqlObjectType);
		}
	}
}

Unit Test for the DAO Class using Mockito (with Spring Boot 1.4.1.RELEASE or higher)

package com.example.sample.unit.test.SampleUnitTestsSB_141.dao.mockito;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.junit4.SpringRunner;

import com.example.sample.unit.test.SampleUnitTestsSB_141.dao.ExampleDAOImpl;

@RunWith(SpringRunner.class) // since 1.4.X version we can use this annotation to run the test using SB features
public class ExampleDAOImplTest {
	
	// include the query because if you change the query accidentally the test case will fail (it's a good checkpoint)
	final static String QUERY_FIND_ALL = " SELECT * FROM TEST ";
	
	// SpyBean instantiates the subject of test, injects the mocked dependencies and invokes the real object methods
	@SpyBean
	ExampleDAOImpl exampleDAOImpl;
	
	// mock the autowired dependency of the test subject		
	@MockBean
	DataSource dataSourceMock;
	
	// mocks the connection used by the DataSource mock
	@MockBean
	Connection connectionMock;
	// mocks the prepared statment used by the DataSource mock
	@MockBean
	PreparedStatement preparedStatementMock = null;
	// mocks the result set used by the DataSource mock
	@MockBean
	ResultSet resultSetMock = null;

	// used to assert and catch the expected exceptions thrown by the test subject
	@Rule
	public ExpectedException thrown = ExpectedException.none();
	
	// expect values to be returned by the dao
	private Map<String,String> expectedNames;
	
	// executed before each test case method -> initializes the expected values
	@Before
	public void setUp() {
		expectedNames = new HashMap<>();
		
		for (int i = 1; i < 6; i++) {
			expectedNames.put(String.valueOf(i), "Name "+ i);
		}
		
		// we don't need initializes the mocked objects and their dependencies -> Spring Boot doing that 🙂 
		// MockitoAnnotations.initMocks(this);
	}
	
	@Test
	public void findAllWithValidArgumentsShouldReturnAMapWithAllNames() throws Exception {
		// you can use in static way or do a static import
		// mocks the expected behavior for the DAO in this test case
		// important: you will test only the logic and the coverage of the test subject so mock the dependencies for that
		Mockito.doReturn(connectionMock).when(dataSourceMock).getConnection();
		Mockito.doReturn(preparedStatementMock).when(connectionMock).prepareStatement(QUERY_FIND_ALL);
		Mockito.doReturn(resultSetMock).when(preparedStatementMock).executeQuery();
		
		// mocks the ResultSet iteration and sets the expect results
		// you can chain the expected behavior of the iteration
		Mockito.doReturn(true).doReturn(true).doReturn(true).doReturn(true).doReturn(true).doReturn(false).when(resultSetMock).next();
		Mockito.doReturn("1").doReturn("2").doReturn("3").doReturn("4").doReturn("5").when(resultSetMock).getString(1);
		Mockito.doReturn(expectedNames.get("1"))
			.doReturn(expectedNames.get("2"))
			.doReturn(expectedNames.get("3"))
			.doReturn(expectedNames.get("4"))
			.doReturn(expectedNames.get("5"))
			.when(resultSetMock).getString(2);
		
		// mocks the finally block
		Mockito.doNothing().when(resultSetMock).close(); // the close method is a void method so you don't expect any result
		Mockito.doNothing().when(preparedStatementMock).close();
		Mockito.doNothing().when(connectionMock).close();
		
		// invokes the test subject that uses the mocked behaviors		
		Map<String,String> result = exampleDAOImpl.findAll();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.size(), equalTo(expectedNames.size()));
		assertThat(result.get("1"), equalTo(expectedNames.get("1"))); // should be "Name 1"
		assertThat(result.get("1"), equalTo("Name 1")); // another way for the previous assertion
		assertThat(result.get("2"), equalTo(expectedNames.get("2")));
		assertThat(result.get("3"), equalTo(expectedNames.get("3")));
		assertThat(result.get("4"), equalTo(expectedNames.get("4")));
		assertThat(result.get("5"), equalTo(expectedNames.get("5")));
		
		// indicates to Mockito that verifies if the mocked objects were called
		Mockito.verify(dataSourceMock).getConnection();
		// you should include Mockito.verify for each mocked method and object
	}

	@Test
	public void findAllWithValidArgumentsShouldThrowASQLExceptionWhenGetConnectionThrowsAnException() throws Exception {
		SQLException expectedException = new SQLException("Get Connection Exception");

		// should be before the test subject method invocation
		// indicates that the test case expects an exception of SQLException class with this message
		thrown.expect(SQLException.class);
		thrown.expectMessage(expectedException.getMessage());
				
		// forces to throw an exception from the service to test the controller's catch code
		Mockito.doThrow(expectedException).when(dataSourceMock).getConnection();
		
		// mocks the finally block
		Mockito.doNothing().when(resultSetMock).close(); // the close method is a void method so you don't expect any result
		Mockito.doNothing().when(preparedStatementMock).close();
		Mockito.doNothing().when(connectionMock).close();

		// invokes the test subject that uses the mocked behaviors		
		// don't expect any assert because the DAO method should thrown an Exception
		exampleDAOImpl.findAll();
				
		Mockito.verify(dataSourceMock).getConnection();
		// you should include Mockito.verify for each mocked method and object
	}	
}

Unit Test for the DAO Class using Mockito (with Spring Boot 1.3.8.RELEASE or lower)

package com.example.sample.unit.test.SampleUnitTestsSB_138.dao.mockito;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import com.example.sample.unit.test.SampleUnitTestsSB_138.dao.ExampleDAOImpl;

//we don't have the @RunWith(SpringRunner.class) annotation -> we use the pure Mockito annotations
public class ExampleDAOImplTest {
	
	// include the query because if you change the query accidentally the test case will fail (it's a good checkpoint)
	final static String QUERY_FIND_ALL = " SELECT * FROM TEST ";
	
	// instantiates the subject of test and injects the mocked dependencies
	@InjectMocks // use to inject mocked objects in spring boot versions lower than 1.4
	ExampleDAOImpl exampleDAOImpl;
	
	// mock the autowired dependency of the test subject	
	// we don't have the @MockBean in spring boot versions lower than 1.4 -> we use @Mock
	@Mock
	DataSource dataSourceMock;
	// mocks the connection used by the DataSource mock
	@Mock
	Connection connectionMock;
	// mocks the prepared statment used by the DataSource mock
	@Mock
	PreparedStatement preparedStatementMock = null;
	// mocks the result set used by the DataSource mock
	@Mock
	ResultSet resultSetMock = null;

	// used to assert and catch the expected exceptions thrown by the test subject
	@Rule
	public ExpectedException thrown = ExpectedException.none();
	
	// expect values to be returned by the dao
	private Map<String,String> expectedNames;
	
	// executed before each test case method -> initializes the expected values
	@Before
	public void setUp() {
		expectedNames = new HashMap<>();
		
		for (int i = 1; i < 6; i++) {
			expectedNames.put(String.valueOf(i), "Name "+ i);
		}
		
		// initializes the mocked objects and injects the mocks to the object with @InjectMocks 
		MockitoAnnotations.initMocks(this);
	}
	
	@Test
	public void findAllWithValidArgumentsShouldReturnAMapWithAllNames() throws Exception {
		// you can use in static way or do a static import
		// mocks the expected behavior for the DAO in this test case
		// important: you will test only the logic and the coverage of the test subject so mock the dependencies for that
		Mockito.doReturn(connectionMock).when(dataSourceMock).getConnection();
		Mockito.doReturn(preparedStatementMock).when(connectionMock).prepareStatement(QUERY_FIND_ALL);
		Mockito.doReturn(resultSetMock).when(preparedStatementMock).executeQuery();
		
		// mocks the ResultSet iteration and sets the expect results
		// you can chain the expected behavior of the iteration
		Mockito.doReturn(true).doReturn(true).doReturn(true).doReturn(true).doReturn(true).doReturn(false).when(resultSetMock).next();
		Mockito.doReturn("1").doReturn("2").doReturn("3").doReturn("4").doReturn("5").when(resultSetMock).getString(1);
		Mockito.doReturn(expectedNames.get("1"))
			.doReturn(expectedNames.get("2"))
			.doReturn(expectedNames.get("3"))
			.doReturn(expectedNames.get("4"))
			.doReturn(expectedNames.get("5"))
			.when(resultSetMock).getString(2);
		
		// mocks the finally block
		Mockito.doNothing().when(resultSetMock).close(); // the close method is a void method so you don't expect any result
		Mockito.doNothing().when(preparedStatementMock).close();
		Mockito.doNothing().when(connectionMock).close();
		
		// invokes the test subject that uses the mocked behaviors		
		Map<String,String> result = exampleDAOImpl.findAll();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.size(), equalTo(expectedNames.size()));
		assertThat(result.get("1"), equalTo(expectedNames.get("1"))); // should be "Name 1"
		assertThat(result.get("1"), equalTo("Name 1")); // another way for the previous assertion
		assertThat(result.get("2"), equalTo(expectedNames.get("2")));
		assertThat(result.get("3"), equalTo(expectedNames.get("3")));
		assertThat(result.get("4"), equalTo(expectedNames.get("4")));
		assertThat(result.get("5"), equalTo(expectedNames.get("5")));
		
		// indicates to Mockito that verifies if the mocked objects were called
		Mockito.verify(dataSourceMock).getConnection();
		// you should include Mockito.verify for each mocked method and object
	}

	@Test
	public void findAllWithValidArgumentsShouldThrowASQLExceptionWhenGetConnectionThrowsAnException() throws Exception {
		SQLException expectedException = new SQLException("Get Connection Exception");

		// should be before the test subject method invocation
		// indicates that the test case expects an exception of SQLException class with this message
		thrown.expect(SQLException.class);
		thrown.expectMessage(expectedException.getMessage());
				
		// forces to throw an exception from the service to test the controller's catch code
		Mockito.doThrow(expectedException).when(dataSourceMock).getConnection();
		
		// mocks the finally block
		Mockito.doNothing().when(resultSetMock).close(); // the close method is a void method so you don't expect any result
		Mockito.doNothing().when(preparedStatementMock).close();
		Mockito.doNothing().when(connectionMock).close();

		// invokes the test subject that uses the mocked behaviors		
		// don't expect any assert because the DAO method should thrown an Exception
		exampleDAOImpl.findAll();
				
		Mockito.verify(dataSourceMock).getConnection();
		// you should include Mockito.verify for each mocked method and object
	}	
}

Unit Test for the DAO Class using EasyMock

package com.example.sample.unit.test.SampleUnitTestsSB_141.dao.easymock;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.easymock.EasyMock;
import org.easymock.EasyMockRunner;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;

import com.example.sample.unit.test.SampleUnitTestsSB_141.dao.ExampleDAOImpl;

@RunWith(EasyMockRunner.class)
public class ExampleDAOImplTest {
	// include the query because if you change the query accidentally the test case will fail (it's a good checkpoint)
	final static String QUERY_FIND_ALL = " SELECT * FROM TEST ";
	
	// instantiates the subject of test and injects the mocked dependencies
	@TestSubject
	ExampleDAOImpl exampleDAOImpl = new ExampleDAOImpl();
	
	// mocks the autowired dependency of the test subject
	@Mock
	DataSource dataSourceMock;
	// mocks the connection used by the DataSource mock
	@Mock
	Connection connectionMock;
	// mocks the prepared statment used by the DataSource mock
	@Mock
	PreparedStatement preparedStatementMock = null;
	// mocks the result set used by the DataSource mock
	@Mock
	ResultSet resultSetMock = null;

	// used to assert and catch the expected exceptions thrown by the test subject
	@Rule
	public ExpectedException thrown = ExpectedException.none();
	
	// expect values to be returned by the dao
	private Map<String,String> expectedNames;
	
	// executed before each test case method -> initializes the expected values
	@Before
	public void setUp() {
		expectedNames = new HashMap<>();
		
		for (int i = 1; i < 6; i++) {
			expectedNames.put(String.valueOf(i), "Name "+ i);
		}
	}
	
	@Test
	public void findAllWithValidArgumentsShouldReturnAMapWithAllNames() throws Exception {
		// you can use in static way or do a static import
		// mocks the expected behavior for the DAO in this test case
		// important: you will test only the logic and the coverage of the test subject so mock the dependencies for that
		EasyMock.expect(dataSourceMock.getConnection()).andReturn(connectionMock);
		EasyMock.expect(connectionMock.prepareStatement(QUERY_FIND_ALL)).andReturn(preparedStatementMock);
		EasyMock.expect(preparedStatementMock.executeQuery()).andReturn(resultSetMock);
		
		// mocks the ResultSet iteration and sets the expect results
		EasyMock.expect(resultSetMock.next()).andReturn(true);
		EasyMock.expect(resultSetMock.getString(1)).andReturn("1");
		EasyMock.expect(resultSetMock.getString(2)).andReturn(expectedNames.get("1"));
		EasyMock.expect(resultSetMock.next()).andReturn(true);
		EasyMock.expect(resultSetMock.getString(1)).andReturn("2");
		EasyMock.expect(resultSetMock.getString(2)).andReturn(expectedNames.get("2"));
		EasyMock.expect(resultSetMock.next()).andReturn(true);
		EasyMock.expect(resultSetMock.getString(1)).andReturn("3");
		EasyMock.expect(resultSetMock.getString(2)).andReturn(expectedNames.get("3"));
		EasyMock.expect(resultSetMock.next()).andReturn(true);
		EasyMock.expect(resultSetMock.getString(1)).andReturn("4");
		EasyMock.expect(resultSetMock.getString(2)).andReturn(expectedNames.get("4"));
		EasyMock.expect(resultSetMock.next()).andReturn(true);
		EasyMock.expect(resultSetMock.getString(1)).andReturn("5");
		EasyMock.expect(resultSetMock.getString(2)).andReturn(expectedNames.get("5"));
		EasyMock.expect(resultSetMock.next()).andReturn(false);
		
		// mocks the finally block
		resultSetMock.close(); // the close method is a void method so you don't expect any result
		EasyMock.expectLastCall(); // for the void method use expectLastCall
		preparedStatementMock.close();
		EasyMock.expectLastCall();
		connectionMock.close();
		EasyMock.expectLastCall();
		
		// indicates to EasyMock that has to "record" the expected behavior of mock objects
		EasyMock.replay(dataSourceMock, connectionMock, preparedStatementMock, resultSetMock);
		
		// invokes the test subject that uses the mocked behaviors		
		Map<String,String> result = exampleDAOImpl.findAll();
		
		// assert the expected results of the test case
		assertThat(result, notNullValue());
		assertThat(result.size(), equalTo(expectedNames.size()));
		assertThat(result.get("1"), equalTo(expectedNames.get("1"))); // should be "Name 1"
		assertThat(result.get("1"), equalTo("Name 1")); // another way for the previous assertion
		assertThat(result.get("2"), equalTo(expectedNames.get("2")));
		assertThat(result.get("3"), equalTo(expectedNames.get("3")));
		assertThat(result.get("4"), equalTo(expectedNames.get("4")));
		assertThat(result.get("5"), equalTo(expectedNames.get("5")));
		
		// indicates to EasyMock that verifies if the mocked objects were called
		EasyMock.verify(dataSourceMock, connectionMock, preparedStatementMock, resultSetMock);
	}

	@Test
	public void findAllWithValidArgumentsShouldThrowASQLExceptionWhenGetConnectionThrowsAnException() throws Exception {
		SQLException expectedException = new SQLException("Get Connection Exception");

		// should be before the test subject method invocation
		// indicates that the test case expects an exception of SQLException class with this message
		thrown.expect(SQLException.class);
		thrown.expectMessage(expectedException.getMessage());
				
		// forces to throw an exception from the service to test the controller's catch code
		EasyMock.expect(dataSourceMock.getConnection()).andThrow(expectedException);
		
		// mocks the finally block
		resultSetMock.close(); // the close method is a void method so you don't expect any result
		EasyMock.expectLastCall(); // for the void method use expectLastCall
		preparedStatementMock.close();
		EasyMock.expectLastCall();
		connectionMock.close();
		EasyMock.expectLastCall();

		EasyMock.replay(dataSourceMock, connectionMock, preparedStatementMock, resultSetMock);
		
		// invokes the test subject that uses the mocked behaviors		
		// don't expect any assert because the DAO method should thrown an Exception
		exampleDAOImpl.findAll();
				
		EasyMock.verify(dataSourceMock);
	}	
}

Useful documentation and examples
Online Training:

About TDD:

About Spring Boot Test:

About Mockito

About system-rules dependency:

Final notes
The Application and their Unit Tests were tested with Spring Boot versions: 1.5.4.RELEASE, 1.4.1.RELEASE and 1.3.8.RELEASE (without ServletInitiliazer class)

You can get the complete code from my public GitHub repository:
https://github.com/Gabotto/SampleUnitTests

Let me know if you have any problem, comment or new ideas:
WordPress: https://gabelopment.wordpress.com/
Email: gabelopment@gmail.com

Also you can find me at Upwork

See you soon with more development notes…