Skip to main content

Testing the Spring Boot App


So far we have covered the fundamentals of spring boot and spring boot persistence layer.This is continuation of last two post on spring boot.If you have not gone through my previous post ,I would recommend you to go through my previous post.
In this session we would be getting familiar with testing framework and how spring boot can be integrated by test framework.Over the years in almost every industry test driven development become very essential in development cycle.As most company now a days prefer to first write unit testing then go over development.While learning spring boot it it essential to know about test driven development in spring boot as in spring boot makes testing easier than ever.

Getting started with Spring Boot Testing

When it comes to testing there are several different ways that you can write unit test to your application.Before doing any testing first we need to integrate testing framework, Spring boot provides spring-boot-starter-test to add dependency for testing framework.By adding this dependency in pom.xml it will cover most of the testing needed for an application.As spring-boot-starter-test covers wide range of unit test for test driven development framework.Spring-boot-starter-test come with below library-
  • Junit : This is used for all your unit testing
  • Hamcrest : This is used for matching and assertions for unit test
  • Mockito : This is a mocking framework to mock objects while writing unit test
  • Spring Test : This is a testing tools for integration testing support
In this demo we are going to add spring-boot-starter-test dependency and going to construct basic test ,finally we are going to run test and would be covering couple of ways to run test.
Add below dependency in pom.xml -
As while creating maven project ,maven add junit library by default ,since spring-boot-starter-test already provides dependency for junit you can remove default junit dependency.In the above dependency scope is mentioned as test to signifies that the scope of this dependency is test.
As maven generate default test class, we are going to utilize this and going to write basic test case.Open up AppTest class from the src/test/java folder.The AppTest class have many methods and constructor given delete them and construct a single test method.
In the above codebase ,the test case has been written to test the testApp() method of PromoController class.The AssetEquals method is used to assert the value return from the method that we are testing.The simple way to create any test method is to annotate a method with @Test.Now run the test class by right click -> Run as-> Junit Test.After successful runs Junit tab would show green in color if test fails red color would show.There are multiple ways of running Jnuit, you can run Junit by right clicking on project folder run as maven test.One can also run Junit by command line if you have set up maven test command in command line ,simple mvn test command will work.

Unit Testing With Mockito

The previous test that we created was pretty simple.As application grows it is difficult to write unit test this way as in your application will have many dependency.Let's consider we are testing a class which has not been implemented yet and you have no idea of how this class has been implemented.In such case we make use of Mockito,as it provides functionality to mock object and it's behaviour.I am going to test the get method of PromoController.First add get method with Id in PromoController this method will return promotion for given Id.
Create a class name PromoControllerTest as a test class to test above method.
In the above class once you run as Junit test it will fail because while fetching value with Id 1 which is not available in DB when PromoController get method execute. To test this kind of scenario we have to mock this behavior.Add following code in the test class-
Mockito is a popular mock framework which can be used in conjunction with JUnit. Mockito allows you to create and configure mock objects and it's behaviour.Mockito is a big topic in itself.I will explain basic of Mockito needed to mock an object.
Given below some of basic annotations and methods used for mocking-
1. @Mock : To create a mock object we have to annotate by @Mock.By using @Mock at PromotionRepository it is going to mock the implementation this class.
2. @InjectMock : It will inject the mocks marked with @Mock to this instance when it is created.
3. MockitoAnnotations.initMocks(this) : When or where are these instances created? Well, it is done in this line, which resides in the setUp method
4. when() : This is used to output the behaviour of mock object.You call method inside and and thenReturn is used what are you expecting as a result.
5. verify() :It is used to verify the behaviour like how many times you are expecting this method to be called.

Hamcrest Matcher

Though Junit provides feature for asserting and matching ,Hamcrest is a powerful framework used in conjunction with Junit. It provides declarative and readable approach for asserting and matching your test result.
To make all matchers available in your file add an static import. This also makes it easier to find matchers through code completion.
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*;
Hamcrest provides many methods for matching test result ,I will explain the more basic and frequently used one-
  • allOf - matches if all matchers match
  • anyOf - matches if any matchers match
  • not - matches if the wrapped matcher doesn’t match and vice
  • equalTo - test object equality using the equals method
  • is - decorator for equalTo to improve readability
  • hasToString - test Object.toString
  • instanceOf, isCompatibleType - test type
  • notNullValue, nullValue - test for null
  • sameInstance - test object identity
  • hasEntry, hasKey, hasValue - test a map contains an entry, key or value
  • hasItem, hasItems - test a collection contains elements
  • hasItemInArray - test an array contains an element
  • closeTo - test floating point values are close to a given value
  • greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo
  • equalToIgnoringCase - test string equality ignoring case
  • equalToIgnoringWhiteSpace - test string equality ignoring differences in runs of whitespace
  • containsString, endsWith, startsWith - test string matching

Integration Testing Challenges

The last topic that I am going to cover in the continuation of spring boot is the challenges faced while integrating testing.Integration testing is all about testing all pieces of an application working together as they would in any live or production environment.
Some major challenges found in traditional spring app-
1.Container are difficult to test
2.Spring context needs to be available
3.App/Test start up can be slow
4.Database state needs to be consistent
In compare to tradition spring apps the spring boot apps have below challenges discovered-
1.No container ,easier to start up
2.Spring context auto configuration
3.App/Test start up can be slow
4.Database state needs to be consistent

Integration Testing Demo

When it comes to integration testing spring boot apps really start to shine over convention spring application.To convert any Junit test into proper integration test the two basic things needed to make that happen.The first you need to annotate your test class with @RunWith(SpringJUnit4ClassRunner.class) this specifies that you want to run test with SpringJUnit4ClassRunner.The next you have to add @SpringBootTest(classes =App.class) annotation to provide your main spring boot class for your application.
I am going to demonstrate with creating test method for findAll() method of PromotionRepository ,add below lines of code and run as Junit-
Spring boot also provides web integration testing to test spring rest controller.To do web integration testing you have to add @SpringBootTest(classes = YourApplicationMainClass.class, webEnvironment= SpringBootTest.WebEnvironment.DEFINED_PORT) ,webEnvironment as another parameters in the @SpringBootTest annotation.
For web integration testing add below lines of code and run as Junit-
This is all we have to know about testing framework in spring boot.I have covered only basic of testing as my main intention was to teach about testing in spring boot application.In future I will try to come up with separate post for Junit.
You can download the codebase from github...https://github.com/maverickvishnu/springboot-demo
Kindly like and comment if you like this post.You can also give me feedback about my area of improvement.You can also suggest me the list of topic that you want to learn and I will try my best to cover.
I have covered Spring boot in multiple post, hence kindly follow below order to learn completely-

Comments

Popular posts from this blog

Spring Data JPA and @Query Annotation

As in the last post on query DSL, I have discussed about creating various custom finder methods to query in database. You also know that spring data JPA internally form JPQL to query in database. In this module I am going to cover query annotations that spring data JPA provides with some advanced features. @Query annotation In order to define SQL to execute for a Spring Data repository method, we can annotate the method with the @Query annotation — its value attribute contains the JPQL or SQL to execute. In the custom JPA repository we can define multiple query DSL methods to query data from database for different condition. Consider a case where condition being passed in the query are too many. Though you can form custom finder method but the method is going to be very large and cumbersome. In such type of scenario the best way is to write simple method and use @Query annotation on top of method. When the @query annotation is being used spring data JPA ignores the structure of f

Query DSL Overview

This post is the continuation of my previous post on spring data JPA. In this post I would be delving deeply into query DSL.Query DSL is an advanced feature provided by spring data JPA to query data from database. It has less code so less to maintain.By using query DSL one can check query at start up rather than at runtime. I am going to discuss key and concepts require to learn DSL and would learn through example. We will extending the same promo-api that we wrote in last post and would be writing Junit to verify query. DSL stands for a domain specific language and is a customized extension of a software programming language that addresses a specific business or domain. In case of spring data JPA this means the framework is enhancing Java to be better suited for creating and working with JPA query. The spring data JPA query DSL is simply all about finding terms and syntax to work with JPA query more efficiently. To demonstrate how query DSL works ,let us take an example to explain

Spring Data JPA Paging, Sorting, Custom Repository, Auditing and Locking

In this module we will talk about some of advance features that spring data JPA support for developing an enterprise application. They are paging and sorting ,auditing, locking and custom repository. Paging and Sorting As a web application developer if you have to display thousands of records on the UI it is not a good practice to just query database and display it to UI. Spring data JPA provides paging and sorting mechanism to handle such type of scenario. These are most sought problem if you are dealing with a big enterprise application, keeping this into mind spring data JPA has provided in built support for paging and sorting. You can see above that spring data JPA has PagingAndSortingRepository interface and it has findAll method. Sort and Pageable object are getting passed as part of findAll() method parameters. What do you think Pageable does behind the scene. Basically Pageable is an interface and when spring data JPA fetch value from database it limits the result. So inte