dcsimg
 

What Is Spring Testing?

Monday Aug 27th 2018 by Manoj Debnath

Here's an introductory idea about the testing support provided by the Spring framework and how it is applied with Spring Boot.

Testing is a crucial part in the business of software development. It ensures performance and quality of the product. The Java platform supports many testing frameworks. Spring introduces the principle of dependency injection on unit testing and has first-class support for integration testing. This article tries to give a quick introductory idea about the testing support provided by the Spring framework and how it is applied with Spring Boot.

An Overview

Testing is a process that ensures that the quality of the software adheres to the standard laid down by the requirements specification and performs smoothly with the fewest possible glitches. For this, a technique called unit testing is the simplest to achieve and can be applied on all applications in their development. Unit testing allows each component of the application to be tested separately. Further, when these individual components are integrated and tested to ensure that multiple components collaborate to work well in the system, it is called integration testing.

In a development environment, usually test codes are written separately and are not mixed with the normal code. In fact, testing a program is distinctly a separate project and is stored in a separate directory. The tests constitute test cases that are applied to test the application manually or automatically. Automated test cases are applied repeatedly at different phases of the software development process. This, by the way, is the most recommended process of the Agile framework. And Spring, being a proponent of the framework, readily supports it.

Java is never lacking in support and has numerous testing frameworks—such as JUnit, TestNG, Mockito, and so forth—at its disposal. They also go pretty well with Spring, yet perhaps the distinctive quality is Spring's incorporation of IoC into the game.

Unit Testing

The major advantage of applying dependency injection is that it makes a program code much easier to be tested because the code is much less dependent on the container, as may be the case with other development. The POJOs are individually testable by simple instantiation without adhering to any dependency. Sometimes, the fine line between unit and integration testing overlaps at the best interest of testing and we need to go beyond unit testing and start performing integration testing without deploying the application or connecting to another infrastructure. In such a case, we can mock objects to obtain the value of integration yet test our code in isolation. For example, we can test a service layer or a controller by stubbing or mocking DAO objects, without actually accessing the persistent data.

The Spring framework provides numerous mock objects and support classes. Some of them are as follows.

Mock Objects

The package called org.springframework.mock.env contains classes that are useful for creating out-of-container unit tests that depend on environment specific properties:

  • MockEnvironment: This class is a mock implementation of the Environment interface.
  • MockPropertySource: This class is a mock implementation of the PropertySource abstract class.

The org.springframework.mock.jndi package contains classes which can be used to set up a JNDI environment for test suites or standalone applications.

  • ExpectedLookupTemplate: An extension of JndiTemplate and essentially creates a mock object of its type.
  • SimpleNamingContext: Implementation of JNDI naming context that binds plain objects to String names for a test environment as well as standalone applications.
  • SimpleNamingContextBuilder: This is an essentially a builder pattern class of the SimpleNamingContext.

There are several classes under org.springframework.mock.web. These classes enable us to create a comprehensive mock object for Servlet APIs. These mock objects are particularly useful for testing Web context, controllers, and filters.

The classes in the org.springframework.mock.http.server.reactive package help in creating a mock for ServerHttpRequest and ServerHttpResponse for WebFlux applications.

Apart from these, there are quite a number of utility classes in the org.springframework.test.util package, such as the ReflectionTestUtils, which is a collection for reflection-based utility methods used in both unit and integration testing. The ModelAndViewAssert class contained in org.springframework.test.web can be used to test Spring MVC ModelAndView objects.

Integration Testing

The Spring support for integration testing enables one to perform integration testing without actually deploying the application server or connecting to other dependent infrastructures. This is a huge plus point because it enables us to test the wiring of Spring IoC container contexts. Also, for example, we can test data source accessibility, or SQL statements by using JDBC, an ORM tool. The package org.springframework.test container has all the required classes for integration testing with the Spring container.

Spring Boot

Spring Boot provides a set of utilities and annotation to help in the process of unit and integration testing and, of course, makes life easier. The core items for the testing are contained in the modules called spring-boot-test and the configuration is provided by the modules called spring-boot-test-autoconfigure.

We can simply use the spring-boot-starter-test in pom.xml and transitively pull all the required dependencies in a Spring application. The support libraries for testing as pulled by the Maven file are as follows:

  • JUnit: It is the standard Java unit testing framework which provides an up-to-date foundation for developer-side testing on the JVM.
  • Spring Test: Utilities and Integration support for Spring Boot applications.
  • AssertJ: A set of assertions to provide meaningful error messages that leverage readability and easy debugging.
  • Hamcrest: Provides a library of matcher object that helps in creating flexible expressions.
  • Mockito: Java Mocking framework.
  • JSONassert: Helps in writing JSON unit test and testing REST interfaces.
  • JsonPath: Xpath for Json.

Spring Boot provides a volley of annotation to designate a test class and test specific parts of an application. For example, we can use @SpringBootTest annotation to enable Spring Boot test features. This annotation loads ApplicationContext used in a test, through SpringApplication. Typically, the @SpringBootTest annotation is used in association with @RunWith(SpringRunner.class) and does a whole lot of thing behind the scene apart from just loading ApplicationContext and having spring beans auto wired to the test instances. The @SpringBootTest does not start the server by default. As a result, to test Web endpoints, we can use a mock environment as follows.

Here is a code snippet to illustrate the idea.

package org.springboot.app;
import static org.springframework.test.web.servlet
   .request.MockMvcRequestBuilders.*;
import org.junit.*;
import org.junit.runner.RunWith;
import org.springboot.app.controller.*;
import org.springframework.boot.test.autoconfigure.
   web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet
   .setup.MockMvcBuilders;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SpringbootApp1ApplicationTests {
   private MockMvc mock;
   @Before
   public void init() {
      mock = MockMvcBuilders
         .standaloneSetup(new BookController()).build();
   }
   @Test
   public void testBookList() throws Exception {
      mock.perform(get("/")).andExpect(status()
         .isOk()).andExpect(view().name("bookList"))
         .andDo(print());
   }
   // ...
}

Conclusion

The Spring test framework integrates well with test frameworks such as Junit, Mockito, and so on. As a result, unit and integration testing becomes easy with a more meaningful outcome. Springs makes it simpler by leveraging annotation-based support. For example, to unit and integration test the Spring TestContext framework, we can use @RunWith, @WebAppConfiguration, and @ContextConfiguration to load a Spring configuration and inject WebApplicationContext into the MockMvc.

This write-up is just a tip of the iceberg and provides a glimpse of what Spring offers with respect to unit and integration testing. Refer to the following links for a more elaborate explanation on this topic.

References

Home
Mobile Site | Full Site