Spring MVC test framework

The Spring MVC test framework makes unit testing and integration testing of the Spring MVC controller more meaningful by offering first class JUnit support. It helps in testing all the aspects of the controller method that have not been tested before. It allows us to test these aspects in depth without starting a web container.

In order to perform a test on the Spring MVC framework, the Spring TestContext framework along with JUnit or TestNG makes it so simple by providing an annotation-driven unit and integration testing support. The Spring TestContext framework can be tested by annotations such as, @RunWith, @WebAppConfiguration, and @ContextConfiguration, to load the Spring configuration and inject the WebApplicationContext into the MockMvc for the unit and the integration test.

Required dependencies

We can configure the Spring TestContext framework by updating pom.xml with the required dependencies, such as spring-test, junit, and mockito-all. The following table explains them in detail:

Group ID

Artifact ID

Version

Description

org.springframework

spring-test

3.2.4 release

It supports unit and integration testing of the Spring components

org.mockito

mockito-all

1.9.5

The library of the Mockito mocking framework

JUnit

junit

4.10

The library of the JUnit framework

You'll find the following code at pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.packt.Spring.chapter7.springmvc</groupId>
   <artifactId>SpringMVCPayrollSystem</artifactId>
   <packaging>war</packaging>
   <version>0.0.1-SNAPSHOT</version>
   <name>SpringMVCPayrollSystem Maven Webapp</name>
   <url>http://maven.apache.org</url>
   <properties>
      <spring.version>3.2.0.RELEASE</spring.version>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-core</artifactId>
         <version>${spring.version}</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
         <version>${spring.version}</version>
      </dependency>
      <!-- Servlet -->
      <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>servlet-api</artifactId>
         <version>2.5</version>
         <scope>provided</scope>
      </dependency>
      <!-- Test -->
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-test</artifactId>
         <version>3.2.4.RELEASE</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.mockito</groupId>
         <artifactId>mockito-all</artifactId>
         <version>1.9.5</version>
      </dependency>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.10</version>
         <scope>test</scope>
      </dependency>
   </dependencies>
   <build>
      <finalName>SpringMVCPayrollSystem</finalName>
   </build>
</project>

Annotations in Spring testing

The Spring Framework provides the annotations that can be used to perform unit and integration testing with the TestContext framework. Here, we will discuss the two important annotations: @ContextConfiguration and @WebAppConfiguration.

The @ContextConfiguration annotation

This annotation is used to set ApplicationContext for the test classes by taking the actual configuration file with the file path. In the following code, we have given the file, so it will take the relative path as the root package. We can also give the exact path by specifying the file: prefix. Also, we can pass more than one configuration file using a comma separator, as shown here:

@ContextConfiguration ({"classpath*: SpringDispatcher-servlet.xml"})
public class EmployeeControllerTestWithMockMvc {
   // class body
}

The @ContextConfiguration annotation caches the ApplicationContext for us and puts it in the static memory for the entire duration of the test or the test suite. And the entire test executes it in the same JVM because ApplicationContext is stored in the static memory. If the second JVM is there, it will not have access to the static context, and it will result in a second ApplicationContext being created.

The @WebAppConfiguration annotation

It is a class-level annotation used to create a web version of the application context in the Spring Framework. It is used to denote that the ApplicationContext, which is loaded for an integration test and used by that class, is an instance of WebApplicationContext. It is important to note that the @WebAppConfiguration annotation must be used with the @ContextConfiguration annotation:

@WebAppConfiguration
@ContextConfiguration ({"classpath*: SpringDispatcher-servlet.xml"})
public class EmployeeControllerTestWithMockMvc {
   // class body
}

MockMvc

The MockMvc is a key part of the Spring MVC Test framework, which can be used to write the tests for the applications developed using the Spring MVC. It is the entry point for Spring MVC testing. The MockMvc mock the entire Spring MVC infrastructure and is created using the implementations of the MockMvcBuilder interface. In order to use the Spring MVC testing, the first step is to create an instance of MockMvc. There are four static methods in the MockMvcBuilders class.

They are as follows:

  • ContextMockMvcBuilder annotationConfigSetup(Class…configClasses): Use this method when you need to configure the application context using Java configuration.
  • ContextMockMvcBuilder xmlConfigSetup(String… configLocations): Use this method when you need to configure the application context by using the XML configuration files.
  • StandaloneMockMvcBuilder standaloneSetup(Object… controllers): You can use this method when you need to configure the test controller manually, and when you want to run the individual components for testing. We don't need to configure the entire application context; instead we only need to configure and execute the associated controller component files.
  • InitializedContextMockMvcBuilder webApplicationContextSetup(WebApplicationContext context): This method must be used when you have already fully initialized the WebApplicationContext object.

Here, we have created the MockMvc instance using MockMvcBuilders and calling the standaloneSetup() method after passing an instance of the controller class as a parameter and then building it by calling the build() method, as shown in the following code snippet:

private MockMvc mockMvc;

   @Before
   public void setup() {
         this.mockMvc = MockMvcBuilders.standaloneSetup (employeeController).build();
   }

Once we have an instance of MockMvc, we can perform the testing using MockMvc. We can send the HTTP request after specifying all the details, such as the HTTP method, the content type, and so on. And then, we can verify the results.

Assertion

To perform the assertion, first we use the instance of MockMvc and then we call the perform() method to pass a relative path to run the test case. And then, we can verify the different components inside the controller using andExpect. The andExpect(status().isOk()) is used to check for a 200 status. Similarly, we can perform the contentType validation, the xpath validation, validate data in the model, URL validation, and the view name validation.

The sample code for this is as shown here:

this.mockMvc
                      .perform(get("/employee"))
                      .andExpect(status().isOk())
                      .andExpect(view().name("hello"))
                      .andExpect(model().attribute("name", "Hello World!"))
                      .andExpect(
                                   model().attribute("greetings",
                                               "Welcome to Packt Publishing - Spring MVC !!!"));

@RunWith(SpringJUnit4ClassRunner.class)

This is a JUnit annotation. It executes the tests in a class annotated by the @RunWith annotation, or extends a class annotated by the @RunWith annotation by invoking the class passed as a parameter, which means that the tests in the annotated class are not executed by the in-built API in the JUnit framework, the runner class used to execute the test case. In order to use the Spring's JUnit class runner for running the test cases within the Spring's ApplicationContext environment, passed spring's SpringJUnit4ClassRunner class as parameter.

So now, we have the complete code to perform the testing of the EmployeeController controller using the Spring MVC test framework. We will use the MockMvc that will mock the entire Spring MVC infrastructure. We will create a MockMvc instance in the method annotated by the @Before annotation, so that it will be available before the test starts.

You'll find this code in EmployeeControllerTestWithMockMvc.java:

package org.packt.Spring.chapter7.springmvc.controller;

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

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.packt.Spring.chapter7.springmvc.controller.EmployeeController;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({ "classpath*:SpringDispatcher-servlet.xml" })
public class EmployeeControllerTestWithMockMvc {

   @InjectMocks
   private EmployeeController employeeController;

   private MockMvc mockMvc;

   @Before
   public void setup() {
          MockitoAnnotations.initMocks(this);
          this.mockMvc = MockMvcBuilders.standaloneSetup(employeeController).build();
   }

   @Test
   public void testHome() throws Exception {

          this.mockMvc
                      .perform(get("/employee"))
                      .andExpect(status().isOk())
                      .andExpect(view().name("hello"))
                      .andExpect(model().attribute("name", "Hello World!"))
                      .andExpect(
                                   model().attribute("greetings",
                                                "Welcome to Packt Publishing - Spring MVC !!!"));
   }
}

Now, we can run the test case by right-clicking on the test and then choosing Run As | JUnit Test. We can verify in the JUnit view as the test case should run successfully, as shown here:

@RunWith(SpringJUnit4ClassRunner.class)
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.9.139