Enterprise Spring boot testing: Part 1 ( Significance, Types of tests, libraries, project setup )
Writing test cases is as important or more important than the actual code that you write. If writing the code is like building a car, test cases represent the quality control that validates the proper working of components as per the specifications.
Significance of test cases.
Test cases are an industry standard for quality software. The coverage provided by the test cases ( how much logic, conditions are covered and tested) will decide the overall score of your project by many code analysis software ( eg: SonarQube )
When we write test cases, we create scenarios ( or input ) that match certain criteria and ensure that the business logic applied and the output are as per the specifications or the requirements.
We use different techniques for mimicking a scenario and the most important is mocking. Here, we intercept some of the underlying dependent objects and alter their behavior to generate the case we are testing.
After that, we use assertions to ensure that the output is in agreement and that the conditions are satisfied.
The idea is to have the test case validate the code and then report an error when something is not satisfied. This will ensure that if someone else alters the code without understanding the full logic, a test case would break indicating that a required or existing business logic is not working. This ensures the overall quality and the integrity of the software.
Types of testing
These are used to validate the individual units of codes ( could be methods ) and verify that the logic is correct. Here, we are only concerned about the exact unit of function and not the underlying dependencies and how they behave. So all the dependencies are being mocked to provide the desired data for the unit being tested.
For testing a customer registration method, we will be mocking the database layer that saves or retrieves the customer and only test the actual logic of what is happening to the object. Similarly, for the case of testing the web layer ( controllers ), we would mock service and other layers.
Integration test includes testing of functionality involving all the layers ( Database, other services, Web MVC ), etc. Here we don’t use mocks and are usually run on dedicated environments.
There are several libraries available for testing in the Spring boot ecosystem. We will be focussing on the ones that come as part of the default
spring-boot-starter-test dependency. These libraries assist in setting up the mocks for Unit testing, assertions utility methods for validating the output, and also different options of mocking the MVC, JPA, and other layers. We will get familiarised with the following libraries.
This is the most common library that provides the basic structure for the testing. This includes the below sub-libraries
- JUnit standard
Together, they provide the foundation of Spring boot testing and include basic annotations like @Test, etc. Read more
This is a mocking framework for providing the support for generating mocks of dependencies that are crucial for unit testing. It has fluid methods that make the tests readable when mocking and a ton of utility methods for parsing and verifying the interactions with the mocks. Read more
This class is the entry for the Spring web layer testing support. It encapsulates all web application beans and makes them available for testing. We have the flexibility to configure the web components ourselves or have Spring boot auto-configure the web layer for us using the application configuration. Read more
We will be creating a very simple web application that contains only one entity as “Customer”. The Customer will be having a few fields and the objective is to have the following functionality for the customer.
- Register customer: Accept the customer information and create the customer in the DB
- Activate customer: Set the status to ACTIVE
- Deactivate customer: Set the status to INACTIVE
We will be covering all the layers ( domain, repository, service, and controllers ) and see how to write the test cases for each of them. In the process, we will also get familiarised with the different annotations, methods, and other utilities that we can use during testing for accomplishing a particular case.
The entire source code for the project ( along with the test cases ) is available under the GitHub repository. You may refer to the same, but I would recommend creating the class and the methods by yourself to get a hands-on experience.
Creating the project
We will head over to https://start.spring.io ( a web-based spring boot project initializer from the Spring team for the quick bootstrap of Spring boot projects ) and create the project with a configuration similar to the below screenshot.
- Maven project ( You may use Gradle if you are comfortable with it)
- Version: 2.5.6 ( latest stable )
- Spring Web
- H2 database
- Spring Data JPA
The h2 database is an in-memory database and will be embedded. That should be good for our testing purposes. You may choose to use MySQL if you want to persist the data.
You may note that we have not included any dependency for testing. That’s because the spring initializer ( start.spring.io) will include the dependency by default. You should be able to see the below dependency in the pom.xml when you open it.
org.springframework.boot spring-boot-starter-test test
Once the configuration is done, you can generate the project and open it in your favorite IDE. I am using IntelliJ. We will create some folders in the project for structuring the classes.
Create the below packages under src
- domain: Holds the domain and entity classes
- repository: Our repository classes for the entities
- services: Services that hold business logic
- controllers: Holding the controllers ( MVC )
- dictionary: Any enums or other dictionary data used by the projects
In the test folder, we will just create a “customers” folder which will hold the test classes related to that business domain.
The final thing is to have the configuration for running the project and the H2 database configuration specified. Let’s delete the default application.properties file in src/resources and create a new application.yml file with the below content.
spring: profiles: active: test --- spring: profiles: test application: name: springtest version: ^project.version^ datasource: url: jdbc:h2:mem:spring-test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE platform: h2 username: sa password: driverClassName: org.h2.Driver jpa: database-platform: org.hibernate.dialect.H2Dialect properties: hibernate: show_sql: true use_sql_comments: true format_sql: true generate-ddl: true h2: console: enabled: true path: /console settings: trace: false web-allow-others: false server: servlet: context-path: /springtest port: 50022
You can see that we have configured the port, context path, and the h2 database configuration in the spring JPA under the “test” profile.
At this point, you could run the project and it should start the web application running in port 50022.
Conclusion & Part 2
In the next part, we will add the Customer entity and the domain methods, and the domain class unit test cases covering the basics of the unit test cases.