Alexey Zvolinskiy

About Alexey Zvolinskiy

Alexey is a test developer with solid experience in automation of web-applications using Java, TestNG and Selenium. He is so much into QA that even after work he provides training courses for junior QA engineers.

Spring MVC: Introduction in testing

Testing is one of the most important parts of software development. Well organized testing helps to keep a code of application in a good state, in a working state. There are a lot of different types of test and methodologies. In this article I want to make an introduction in unit testing of applications based on Spring MVC. Don’t hope to read all about Spring MVC testing here, because it’s just a first article about unit testing.

Speak about unit testing without some application, which I’m going to test is deception. I’ll use one of my applications from the previous post, to avoid a gossip. I
 
recommend to make a short overview of the application before you proceed read current post. The main goal of this tutorial is to demonstrate how to configure unit tests for a Spring MVC application in annotation maner.

Preparations

The first thing which we always have to do before start any development – add of new dependencies in Maven’s pom.xml file. This case isn’t an exception.

...
		<dependency>
			<groupid>org.springframework</groupid>
			<artifactid>spring-test</artifactid>
			<version>${spring.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupid>org.springframework</groupid>
			<artifactid>spring-test-mvc</artifactid>
			<version>1.0.0.M1</version>
			<scope>test</scope>
		</dependency>
...
	<repositories>
		<repository>
			<id>spring-maven-milestone</id>
			<name>Spring Maven Milestone Repository</name>
			<url>http://maven.springframework.org/milestone</url>
		</repository>
	</repositories>
...

I have added two new dependencies:

  1. #1 spring-test
  2. #2 spring-test-mvc

The first one is for support for testing Spring applications with tools such as JUnit and TestNG. This artifact is generally always defined with a ‘test’ scope for the integration testing framework and unit testing stubs. The second one is for testing Spring MVC server-side and client-side RestTemplate-based code. Pay your attention that I added a new repository. I did this because spring-test-mvc still isn’t in official maven repository.

Controller for the unit tests

In this post I’m going to write two unit tests for the most simple controller. Here is a code of the controller:

@Controller  
    public class LinkController {  

        @RequestMapping(value="/")  
        public ModelAndView mainPage() {  
            return new ModelAndView("home");  
        }  

        @RequestMapping(value="/index")  
        public ModelAndView indexPage() {  
            return new ModelAndView("home");  
        }  

    }

So as you can see the methods in the controller is trivial, they just return some JSP. The testing of the controller implies check of request status (in success case the code should be 200) and verification of the view’s name.

Writing of unit tests for Spring MVC

Here is a quote of Petri Kainulainen:

The heart of the spring-test-mvc is a class called MockMvc that can be used to write tests for any application implemented by using Spring MVC. Our goal is to create a new MockMvc object by using the implementations of the MockMvcBuilder interface. The MockMvcBuilders class has four static methods which we can use to obtain an implementation of the MockMvcBuilder interface. These methods are described in following:

  • ContextMockMvcBuilder annotationConfigSetup(Class… configClasses) method must be used when we are using Java configuration for configuring the application context of our application.
  • ContextMockMvcBuilder xmlConfigSetup(String… configLocations) must be used when the application context of our application is configured by using XML configuration files.
  • StandaloneMockMvcBuilder standaloneSetup(Object… controllers) must be used when we want to configure the tested controller and the required MVC components manually.
  • InitializedContextMockMvcBuilder webApplicationContextSetup(WebApplicationContext context) must be used when we have already created a fully initialized WebApplicationContext object.

I’m going to use the Web Application Context, for this purpose I need to create a class with configurations:

package com.sprhib.init;

import org.springframework.context.annotation.*;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.*;

@Configuration
@ComponentScan("com.sprhib")
@EnableWebMvc
public class BaseTestConfig {

	@Bean
	public UrlBasedViewResolver setupViewResolver() {
		UrlBasedViewResolver resolver = new UrlBasedViewResolver();
		resolver.setPrefix("/WEB-INF/pages/");
		resolver.setSuffix(".jsp");
		resolver.setViewClass(JstlView.class);
		return resolver;
	}

}

And finally the class with the tests:

package com.sprhib.test;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
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;
import org.springframework.web.context.WebApplicationContext;

import com.sprhib.init.BaseTestConfig;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes=BaseTestConfig.class)
public class LinkControllerTest {

	@Autowired
	private WebApplicationContext wac;

	private MockMvc mockMvc;

	@Before
	public void init() {
		mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
	}

	@Test
	public void testHomePage() throws Exception {
		mockMvc.perform(get("/"))
			.andExpect(status().isOk())
			.andExpect(view().name("home"));
	}

	@Test
	public void testIndexPage() throws Exception {
		mockMvc.perform(get("/index.html"))
			.andExpect(status().isOk())
			.andExpect(view().name("home"));
	}

}

Notice that I have used static imports they provide usage of such methods as get(), status() etc. @WebAppConfiguration is a class-level annotation that is used to declare that the ApplicationContext loaded for an integration test should be a WebApplicationContext. Look at the project structure after I have added all testing stuff:

Check the project on GitHub. I hope everything is clear. Spring test MVC project is a good tool for the testing of the appropriate applications. There’s just one cons lack of documentation and tutorials. In the next tutorials I’m going to develop this theme.
 

Reference: Spring MVC: Introduction in testing from our JCG partner Alexey Zvolinskiy at the Fruzenshtein’s notes blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

5 Responses to "Spring MVC: Introduction in testing"

  1. Nice article Alexey. I have a few things to add. First of all I do not understand why do you need both spring-test and spring-test-mvc? This is only needed when you have older spring versions and this should be mentioned explicitly. There is a list of things which you CAN and which you cannot do with standalone context – otherwise Rossen would give us only one opportunity. And finally it will be good to have some examples how to mock a service layer in a controllers.

    • Alex Fruzenshtein says:

      Thanks for the comment

      1. As specified in the documentation, spring-test is required for
      testing Spring applications with tools such as JUnit and TestNG. Even
      more, I use static imports in the LinkControllerTest, they are from the
      spring-test dependency.

      2. Regarding testing of a service layer, I will write some articles about it soon.

      • I did not mean the service layer tests. The controller usually depends on some of your services. How in this case you plan to deal with that? That would make an example full.

        • FruzNotes says:

          Usually yes, almost all controllers depend on some service. But in my case I just made the introduction in testing. In the following articles I will extend the application, new tests will use some mock frameworks

  2. i’m ready for the next series :D

Leave a Reply


seven − 7 =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close