Unit Testing of Spring MVC Controllers: Configuration

This blog post is outdated! If you want to learn how you can write unit tests for Spring MVC controllers, you should take a look at my updated Spring MVC Test tutorial. It describes how you can write unit tests for Spring MVC controllers with JUnit 5.

Writing unit tests for Spring MVC controllers has traditionally been both simple and problematic.

Although it is pretty simple to write unit tests which invoke controller methods, the problem is that those unit tests are not comprehensive enough.

For example, we cannot test controller mappings, validation and exception handling just by invoking the tested controller method.

Spring MVC Test solved this problem by giving us the possibility to invoke controller methods through the DispatcherServlet.

This is the first part of my tutorial which describes the unit testing of Spring MVC controllers and it describes how we can configure our unit tests.

Let's get started.

Getting the Required Dependencies with Maven

We can get the required dependencies by declaring the following testing dependencies in our pom.xml file:

  • JUnit 4.11
  • Mockito Core 1.9.5
  • Spring Test 3.2.3.RELEASE

The relevant part of our pom.xml file looks as follows:

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.11</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.mockito</groupId>
	<artifactId>mockito-core</artifactId>
	<version>1.9.5</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-test</artifactId>
	<version>3.2.3.RELEASE</version>
	<scope>test</scope>
</dependency>

Note: If you have to use Spring Framework 3.1, you can write unit tests for your controllers by using spring-test-mvc. This project was included in the spring-test module when Spring Framework 3.2 was released.

Let's move on and take a quick look at our example application.

The Anatomy of Our Example Application

The example application of this tutorial provides CRUD operations for todo entries. In order to understand the configuration of our test class, we must have some knowledge about the tested controller class.

At this point, we need to know the answers to these questions:

  • What dependencies does it have?
  • How is it instantiated?

We can get the answers to those questions by taking a look at the source code of the TodoController class. The relevant part of the TodoController class looks as follows:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;

@Controller
public class TodoController {

    private final TodoService service;

    private final MessageSource messageSource;

    @Autowired
    public TodoController(MessageSource messageSource, TodoService service) {
        this.messageSource = messageSource;
        this.service = service;
    }

	//Other methods are omitted.
}

As we can see, our controller class has two dependencies: TodoService and MessageSource. Also, we can see that our controller class uses constructor injection.

At this point this is all there information we need. Next we will talk about our application context configuration.

Configuring the Application Context

Maintaining a separate application context configurations for our application and our tests is cumbersome. Also, It can lead into problems if we change something in the application context configuration of our application but forget to do the same change for our test context.

That is why the application context configuration of the example application has been divided in a such way that we can reuse parts of it in our tests.

Our application context configuration has been divided as follows:

  • The first application configuration class is called ExampleApplicationContext and it is the "main" configuration class of our application.
  • The second configuration class is responsible of configuring the web layer of our application. The name of this class is WebAppContext and it is the configuration class which we will use in our tests.
  • The third configuration class is called PersistenceContext and it contains the persistence configuration of our application.

Note: The example application has also a working application context configuration which uses XML configuration files. The XML configuration files which correspond with the Java configuration classes are: exampleApplicationContext.xml, exampleApplicationContext-web.xml and exampleApplicationContext-persistence.xml.

Let's take a look at the application context configuration of our web layer and find out how we can configure our test context.

Configuring the Web Layer

The application context configuration of the web layer has the following responsibilities:

  1. It enables the annotation driven Spring MVC.
  2. It configures the location of static resources such as CSS files and Javascript files.
  3. It ensures that the static resources are served by the container's default servlet.
  4. It ensures that the controller classes are found during component scan.
  5. It configures the ExceptionResolver bean.
  6. It configures the ViewResolver bean.

Let's move on and take a look at the Java configuration class and the XML configuration file.

Java Configuration

If we use Java configuration, the source code of the WebAppContext class looks as follows:

mport org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

import java.util.Properties;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {
        "net.petrikainulainen.spring.testmvc.common.controller",
        "net.petrikainulainen.spring.testmvc.todo.controller"
})
public class WebAppContext extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public SimpleMappingExceptionResolver exceptionResolver() {
        SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();

        Properties exceptionMappings = new Properties();

        exceptionMappings.put("net.petrikainulainen.spring.testmvc.todo.exception.TodoNotFoundException", "error/404");
        exceptionMappings.put("java.lang.Exception", "error/error");
        exceptionMappings.put("java.lang.RuntimeException", "error/error");

        exceptionResolver.setExceptionMappings(exceptionMappings);

        Properties statusCodes = new Properties();

        statusCodes.put("error/404", "404");
        statusCodes.put("error/error", "500");

        exceptionResolver.setStatusCodes(statusCodes);

        return exceptionResolver;
    }

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }
}

XML Configuration

If we use XML configuration, the content of the exampleApplicationContext-web.xml file looks as follows:

i<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <mvc:annotation-driven/>

    <mvc:resources mapping="/static/**" location="/static/"/>
    <mvc:default-servlet-handler/>

    <context:component-scan base-package="net.petrikainulainen.spring.testmvc.common.controller"/>
    <context:component-scan base-package="net.petrikainulainen.spring.testmvc.todo.controller"/>

    <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="net.petrikainulainen.spring.testmvc.todo.exception.TodoNotFoundException">error/404</prop>
                <prop key="java.lang.Exception">error/error</prop>
                <prop key="java.lang.RuntimeException">error/error</prop>
            </props>
        </property>
        <property name="statusCodes">
            <props>
                <prop key="error/404">404</prop>
                <prop key="error/error">500</prop>
            </props>
        </property>
    </bean>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    </bean>
</beans>

Configuring the Test Context

The configuration of our test context has two responsibilities:

  1. It configures a MessageSource bean which is used by our controller class (feedback messages) and Spring MVC (validation error messages). The reason why we need to do this is that the MessageSource bean is configured in the "main" configuration class (or file) of our application context configuration.
  2. It creates a TodoService mock which is injected to our controller class.

Let's find out how we configure our test context by using Java configuration class and XML configuration file.

Java Configuration

If we configure our test context by using Java configuration, the source code of the TestContext class looks as follows:

import org.mockito.Mockito;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;

@Configuration
public class TestContext {

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();

        messageSource.setBasename("i18n/messages");
        messageSource.setUseCodeAsDefaultMessage(true);

        return messageSource;
    }

    @Bean
    public TodoService todoService() {
        return Mockito.mock(TodoService.class);
    }
}

XML Configuration

If we configure our test context by using an XML configuration, the content of the testContext.xml file looks as follow:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="i18n/messages"/>
        <property name="useCodeAsDefaultMessage" value="true"/>
    </bean>

    <bean id="todoService" name="todoService" class="org.mockito.Mockito" factory-method="mock">
        <constructor-arg value="net.petrikainulainen.spring.testmvc.todo.service.TodoService"/>
    </bean>
</beans>

Configuring The Test Class

We can configure our test class by using one of the following options:

  1. The Standalone configuration allows us to register one or more controllers (classes annotated with the @Controller annotation) and configure the Spring MVC infrastructure programatically. This approach is a viable option if our Spring MVC configuration is simple and straight-forward.
  2. The WebApplicationContext based configuration allows us the configure Spring MVC infrastructure by using a fully initialized WebApplicationContext. This approach is better if our Spring MVC configuration is so complicated that using standalone configuration does not make any sense.

Let's move on and find out how we can configure our test class by using both configuration options.

Using Standalone Configuration

We can configure our test class by following these steps:

  1. Annotate the class with the @RunWith annotation and ensure that test is executed by using the MockitoJUnitRunner.
  2. Add a MockMvc field to the test class.
  3. Add a TodoService field to the test class and annotate the field with the @Mock annotation. This annotation marks the field as a mock. The field is initialized by the MockitoJUnitRunner.
  4. Add a private exceptionResolver() method to the class. This method creates a new SimpleMappingExceptionResolver object, configures it, and returns the created object.
  5. Add a private messageSource() method to the class. This method creates a new ResourceBundleMessageSource object, configures it, and returns the created object.
  6. Add a private validator() method to the class. This method creates a new LocalValidatorFactoryBean object and returns the created object.
  7. Add a private viewResolver() method to the the class. This method creates a new InternalResourceViewResolver object, configures it, and returns the created object.
  8. Add a setUp() method to the test class and annotate the method with the @Before annotation. This ensures that the method is invoked before each test. This method creates a new MockMvc object by calling the standaloneSetup() method of the MockMvcBuilders class and configures the Spring MVC infrastructure programmatically.

The source code of our test class looks as follows:

import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.context.MessageSource;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

import java.util.Properties;

@RunWith(MockitoJUnitRunner.class)
public class StandaloneTodoControllerTest {

    private MockMvc mockMvc;

    @Mock
    private TodoService todoServiceMock;

    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.standaloneSetup(new TodoController(messageSource(), todoServiceMock))
                .setHandlerExceptionResolvers(exceptionResolver())
                .setValidator(validator())
                .setViewResolvers(viewResolver())
                .build();
    }

    private HandlerExceptionResolver exceptionResolver() {
        SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();

        Properties exceptionMappings = new Properties();

        exceptionMappings.put("net.petrikainulainen.spring.testmvc.todo.exception.TodoNotFoundException", "error/404");
        exceptionMappings.put("java.lang.Exception", "error/error");
        exceptionMappings.put("java.lang.RuntimeException", "error/error");

        exceptionResolver.setExceptionMappings(exceptionMappings);

        Properties statusCodes = new Properties();

        statusCodes.put("error/404", "404");
        statusCodes.put("error/error", "500");

        exceptionResolver.setStatusCodes(statusCodes);

        return exceptionResolver;
    }

    private MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();

        messageSource.setBasename("i18n/messages");
        messageSource.setUseCodeAsDefaultMessage(true);

        return messageSource;
    }

    private LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }

    private ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }
}

Using the standalone configuration has two problems:

  1. Our test class looks like a mess even though our Spring MVC configuration is rather simple. Naturally, we could clean it up by moving the creation of Spring MVC infrastructure components into a separate class. This is left as an exercise for the reader.
  2. We have to duplicate the configuration of Spring MVC infrastructure components. This means that if we change something in the application context configuration of our application, we must remember to do the same change to our tests as well.

Using WebApplicationContext Based Configuration

We can configure our test class by following these steps:

  1. Annotate the test class with the @RunWith annotation and ensure that the test is executed by using the SpringJUnit4ClassRunner.
  2. Annotate the class with the @ContextConfiguration annotation and ensure that the correct configuration classes (or XML configuration files) are used. If we want to use Java configuration, we have to set the configuration classes as the value of the classes attribute. On the other hand, if we prefer XML configuration, we have to set the configuration files as the value of the locations attribute.
  3. Annotate the class with the @WebAppConfiguration annotation. This annotation ensures that the application context which is loaded for our test is a WebApplicationContext.
  4. Add a MockMvc field to the test class.
  5. Add a TodoService field to the test class and annotate the field with the @Autowired annotation.
  6. Add a WebApplicationContext field to the test class and annotate the field with the @Autowired annotation.
  7. Add a setUp() method to the test class and annotate the method with the @Before annotation. This ensures that the method is called before each test. This method has responsibilities: it resets the service mock before each test and create a new MockMvc object by calling the webAppContextSetup() method of the MockMvcBuilders class.

The source code of our test class looks as follows:

import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
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;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestContext.class, WebAppContext.class})
//@ContextConfiguration(locations = {"classpath:testContext.xml", "classpath:exampleApplicationContext-web.xml"})
@WebAppConfiguration
public class WebApplicationContextTodoControllerTest {

    private MockMvc mockMvc;

    @Autowired
    private TodoService todoServiceMock;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Before
    public void setUp() {
        //We have to reset our mock between tests because the mock objects
        //are managed by the Spring container. If we would not reset them,
        //stubbing and verified behavior would "leak" from one test to another.
        Mockito.reset(todoServiceMock);

        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }
}

The configuration of our test class looks a lot cleaner than the configuration which uses standalone configuration. However, the “downside” is that our test uses the full Spring MVC infrastructure. This might be an overkill if our test class really uses only a few components.

Summary

We have now configured our unit test class by using both the standalone setup and the WebApplicationContext based setup. This blog post has taught us two things:

  • We learned that it is important to divide the application context configuration in a such way that we can reuse parts of it in our tests.
  • We learned the difference between the standalone configuration and the WebApplicationContext based configuration.

The next part of this tutorial describes how we can write unit tests for "normal" Spring MVC controllers.

P.S. You can get the example application of this blog post from Github.

92 comments… add one
  • grails dev Jul 21, 2013 @ 12:52

    I love SpringMVC. Since controllers are also POJO's, testing is easy just like testing any other class. And have options like pointed above

  • ola Aug 8, 2013 @ 13:07

    Thank's! Very structured and easy to understand!

    • Petri Aug 8, 2013 @ 22:28

      You are welcome! I am happy to hear that this blog post was useful to you.

  • Jon Oct 8, 2013 @ 18:31

    Nice, thanks for showing how to set MockMvc's view resolver programatically.

  • Martin Dilger Nov 8, 2013 @ 15:41

    Maybe you should also mention (or did you and I overlooked it?) that this project is usable even if you are stuck with a spring version lower than 3.2.x.
    Just use this project (its basically the same as this code base has been imported into the core).

    https://github.com/spring-projects/spring-test-mvc

    • Petri Nov 8, 2013 @ 16:54

      Actually I didn't realize that it would be useful to mention it here. I will update this blog post later today. Thanks for pointing this out!

  • Blebail Apr 14, 2014 @ 18:48

    Thanks for this post,

    I have a little question though :
    In the setUp() method which is executed before each test (@before), a MockMvc is built.
    I totally understant why the todoServiceMock has to be reset before each test, but what about the MockMvc ?
    Would it not be better to build the MockMvc once for all the tests (@beforeClass) ?
    What's the point/utility of rebuilding a MockMvc before each test of the test class ?

    Maybe i missed something here, i'm relatively new to spring mocking strategy :)

    • Petri Apr 14, 2014 @ 21:35

      That is a GREAT question. To be honest, I create a new MockMvc object for each test case just because this is the way it is done in the reference manual of Spring Framework.

      However, now that you mentioned it, I started to wonder if this is really necessary. Unfortunately I cannot answer to your question right now, but I promise that I will try to find an answer to your question. I will let you know if I find it.

      • Blebail Apr 15, 2014 @ 10:36

        Actually I've seen both ways. After a little research in spring sources, I saw it two times in the @beforeClass. So I guess it's ok.

        Example :
        https://github.com/spring-projects/spring-test-mvc/blob/master/src/test/java/org/springframework/test/web/server/samples/context/WarRootDirectoryTests.java

        Anyway, thank you, these tutorials have been and will be really helpful.

        • Petri Apr 15, 2014 @ 20:52

          After I gave this some thought and did some testing, I noticed that using the @BeforeClass annotation isn't very handy for two reasons:

          1. You have to remember to reset your mock objects in your test methods. If you don't do this, your tests will fail when you try to verify the interactions between the tested code and the mock objects.
          2. You cannot inject anything to your test classes because all injected fields are null when the setUp() method is invoked. This means that you cannot use the WebApplicationContext based setup (unless you build the web application context yourself). Of course you can always use the standalone setup as long as you remember to reset your mock objects in your test methods.

          In other words, it seems that

          • It is possible to write unit tests by using this approach but it takes some extra work.
          • It doesn't make sense to write integration tests by using this approach because it takes too much work to configure everything manually.
          • Blebail Apr 16, 2014 @ 18:58

            I did some testing too. And yeah, with the @beforeClass approach I noticed the same issues as you. I'm back to the MockMvc in the @before method.

            Thank you for taking some time to take a look a this and give the proper answer to my question.

          • Petri Apr 16, 2014 @ 19:55

            You are welcome! It is always nice to help someone out (and often I end up learning new things as well).

  • sri May 8, 2014 @ 14:11

    hai petri, thanks for structured explanation of the spring web Mvc
    could plz explain why spring come into picture ? what problems java faced before spring frame work ? And how spring solved those problems ?

    • Petri May 8, 2014 @ 21:10

      IMO the main reason why the Spring Framework became popular was that EJB 2 sucked big time. Writing EJB 2 applications was a complex task and the only way to configure them was to use monstrous XML files. In other words, the only other option, which provided "everything", was so horrible that developers started to use Spring Framework for writing enterprise applications.

      You might want to read an article titled: Why Use the Spring Framework. However, you should remember that things have changed a lot, and the newer Java EE versions are totally different beasts.

  • Tyler May 8, 2014 @ 23:11

    Hi Petri,

    I was following along pretty well until the Test Context configuration. Firstly, at the start of this tutorial I saw that our TodoController declared a TodoService variable. I assumed that the TodoService class would be covered at some time in the tutorial, but it was not. So I lost you on this part: .

    Am I missing something? Where is the TodoService class code? or did I miss a code download somewhere?

    Thanks

    • Petri May 8, 2014 @ 23:42

      Hi Tyler,

      The reason why I didn't describe the TodoService interface in this blog post was that you don't have to know what it is (yet).

      The next parts of this tutorial shed some light to this matter by describing the implementations of the tested controller methods. This tells you what service methods you have to mock in your unit tests.

      By the way, you can get the example application of this blog post from Github.

  • Pravin Jun 5, 2014 @ 21:36

    Hey Petri!

    Excellent Tutorial!

    I have an issue for which I request your help.

    By default, the @WebApplicationContext looks for the main spring XML file in src/main/webapp in a maven project. How do we configure it for non-maven projects.

    I tried this:

    @ContextConfiguration({ "classpath*:mvc-dispatcher-servlet.xml" })
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration({ "classpath*:mvc-dispatcher-servlet.xml" } )
    public class LoginControllerTest {
    // some code
    }

    • Petri Jun 6, 2014 @ 20:47

      If the mvc-dispatcher-servlet.xml file is found from the "root" of your classpath, you can configure your test by using this code:

      
      @ContextConfiguration({"classpath:mvc-dispatcher-servlet.xml"})
      @RunWith(SpringJUnit4ClassRunner.class)
      @WebAppConfiguration
      public class LoginControllerTest {
      // some code
      }
      
      

      Check out the following Javadocs for more details about this:

      I hope that this answered to your question.

  • Prashant Jun 23, 2014 @ 16:21

    Hi Petri,
    Above code with spring 4.0.5 , gives "java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig" exception with below servlet api maven dependency

    javax.servlet
    servlet-api
    3.0-alpha-1
    provided

    Issue was fixed by including maven dependency for "geronimo-servlet_3.0_spec" (ref. https://jira.spring.io/browse/SPR-11049)

    • Sai Aug 13, 2014 @ 21:33

      This was very helpful! Thank you

  • Justen Britain Jul 6, 2014 @ 9:40

    Hi Petri,

    I used your tutorial for setting up Spring Social and am now trying to unit test following this tutorial. The problem I am running into is that Spring-Social's SocialConfiguration class that we extend to setup the social side of the house has a method "usersConnectionRepository" which calls the SocialConfigurer.getUsersConnectionRepository(connectionFactoryLocator. Obviously I don't want a JDBCConnectionFactory being setup and called for unit tests but when I add a bean class to override it in my TestContext class Spring throws an exception say it found 2 matching beans and expected only one. Any help you can provide is appreciated.

  • Binh Thanh Nguyen Jul 9, 2014 @ 6:01

    Thanks, nice post

  • sanjeev Jul 15, 2014 @ 14:13

    Hello Petri,
    Thanks for the post. I have been following the same.
    I am writing unit test based on java config approach.
    I am able to deploy and test the application via rest client such as postman.
    But with Junit I am not sure why I am getting the below error. Is this a configuration problem. Please let me know your input.
    Kind Regards
    Sanjeev.

    
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @ContextConfiguration(classes = {PersistenceConfigODB.class, RootConfig.class, WebConfig.class})
    public class TeamRepositoryTest {
    	private MockMvc mockMvc;
    	
    	@Autowired
    	WebApplicationContext webApplicationContext;
    
    	@BeforeClass
    	public static void setUpBeforeClass() throws Exception {}
    
    	@Before
    	public void setUp() throws Exception {
    		mockMvc = MockMvcBuilders
    						.webAppContextSetup(webApplicationContext)
    						.build();
    	}
    }
    
    

    java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/servlet/SessionTrackingMode

    Update: I removed the unrelated part of the stack trace - Petri

    • Petri Jul 15, 2014 @ 20:39

      I found this blog post which describes a very similar problem and provides a solution to it.

      Is the servlet-api jar file in the classpath when you run your unit tests?

  • OldDevelopper Aug 1, 2014 @ 18:10

    Why test code is far longer than code to be tested ?
    Isn't it a little problem ?
    Who says more code, says more bugs, isn't it ?
    Anyway good job

    • Petri Aug 1, 2014 @ 20:33

      Why test code is far longer than code to be tested ?

      If you are referring to the test methods described in the second and third part of this tutorial, the reason is that those methods test too much. Nowadays I split the test methods into smaller test methods which test only one thing.

      But I think that it is quite common that the LOC of your test code is a lot bigger than the LOC of your production code. This happens if you write comprehensive tests for your code.

      Isn’t it a little problem ?

      Yes. The test methods described in later parts of this tutorial should be splitted into smaller methods.

      Who says more code, says more bugs, isn’t it ?

      Yes. That is why I split my test methods into smaller methods. These methods are typically much simpler which makes it easier to verify that there are no bugs.

      Anyway good job

      Thanks. Also, thank you for asking this important question.

  • martin samm Nov 19, 2014 @ 9:02

    Petri - love the articles; excellent resource. a question - presumably when in normal (non-test) running, something is component scanning to find the 'real' TodoService (web context class?). How do you stop that scanning occurring in testing mode and to use the mock TodoService instead - i cant seem to separate the configs enough to get that to happen - i get the real and mock beans being created and getting startup errors.
    Thanks again.

    • Petri Nov 19, 2014 @ 9:45

      Hi Martin,

      Thank you for your kind words. I really appreciate them.

      How do you stop that scanning occurring in testing mode and to use the mock TodoService instead – i cant seem to separate the configs enough to get that to happen – i get the real and mock beans being created and getting startup errors.

      I separate the application context configuration classes of my application in a such way that the web layer is configured in a single class that also configures the component scan for controllers and other components that belong to the web layer. If I do this, I can then create a separate application context configuration class for my tests that creates the "mock beans".

      If you take a look at the application configuration of my example application, you notice that

      • The ExampleApplicationContext class configures the component scan for components that belong to the service layer.
      • The WebAppContext class configures the component scan for components that belong to the web layer.

      If I write unit tests that use the only the WebAppContext class and the configuration class that creates the mock beans, I can scan only the tested classes.

      A word of warning though:

      When I wrote this tutorial, I used the web application context based setup because it seemed easier than standalone setup. Although this is true for simple applications, maintaining the application context configuration class that creates the "mock beans" can be a bit painful if you are writing tests for a real life application that has a lot beans that should be mocked.

      In other words, sometimes it might be wiser to use the standalone configuration (especially in unit tests).

  • Marcusgao Nov 27, 2014 @ 7:25

    Hi Petri, thanks a lot for your tutorial, it really helps me.
    But unfortunately, i encounter a problem. I noticed that in your project on Github, you have several ApplicationContext files, but you don't mention them in this blog. i do not write any ApplicationContext.java files, and i get this error when testing.

    java.lang.IllegalStateException: Failed to load ApplicationContext
    Caused by: java.lang.IllegalStateException: Cannot load configuration class:

    Does this mean i need to write some ApplicationContext.java files like you do in the project?
    thanks

    • Petri Nov 27, 2014 @ 18:04

      Hi,

      Thank you for your kind words. I really appreciate them.

      Does this mean i need to write some ApplicationContext.java files like you do in the project?

      You are right. You have to configure the application context of your application by using either Java configuration classes or XML configuration files.

      Although you can write unit tests for your controllers by using the standalone configuration (scroll down and look for a string 'Setup Options'), you cannot run your application if you haven't configured its application context.

      The example application of this blog post has unit tests that use the standalone configuration and the web application context based configuration.

      If you have further questions, don't hesitate to ask them!

  • srini Dec 4, 2014 @ 14:40

    Hi Petri,

    exceptation is not invoked it returns null
    using mockmvc with standalone,@Runwith(MockitJunitRunner.class)

    
    @Scope("singleton")
    mycontroller{
    	@autowire
    	myUtil myutil
    	
    	somemethod(req,res){
    	}
    }
    
    
    
    mycontrollerTest{
    	@InjectMocks
    	mycontroller mycont ;
    
    	@Mock
    	myUtil myutil
    
    	@before() { 
    		Mocktoannotation.init(this)
    		this.mockMvc = MockMvcBuilders.standaloneSetup(mycont).build()
    	}
    
    	testsomemethod(){ 
    		when(myutil.getxxx()).thenReturn(yyy);
    		mycont.somemethod(mockreq,mockres);
    	}
    }
    
    

    i debugged the code,the exception which we set is not called ?
    what is i am missing

    Thanks

    • Petri Dec 4, 2014 @ 18:45

      Hi,

      Do you mean that

      1. The getxxx() method of the myUtil class is not invoked at all.
      2. The getxxx() method of the myUtil class is invoked, but it returns null.

      It is kind of hard to say what is wrong because you omitted the source code of your controller method. Could you add the source code of your controller method here?

      By the way, you might want to read a blog post titled: Mockito: Why You Should Not Use InjectMocks Annotation to Autowire Fields. It explains why you should use constructor injection instead of field injection (I have written about this too).

      • Anonymous Dec 4, 2014 @ 19:40

        its mockitocglibproxy called which in term invokes mokito api handler which retruns false due to internal stubbed array is null

      • Rogerio Oct 30, 2015 @ 19:40

        The argument used in [that article](http://tedvinke.wordpress.com/2014/02/13/mockito-why-you-should-not-use-injectmocks-annotation-to-autowire-fields) is very weak: it simply says that, since Mockito will fail *silently* when a new dependency (the `AuditService`) is added, calling the constructor directly in the test would be better as you have to do it explicitly.

        But that is just a specific Mockito limitation, which happens to lack support for annotations like @Autowired. If it had (like another testing library - JMockit - does), then the test would fail with a nice exception message about the missing dependency.

        Constructor injection, in fact, is a bad choice, compared to injection into annotated fields, for the following reasons:
        1. Constructor injection requires more code: you need to have instance fields for the injected dependencies, and also an assignment to each field in the injection constructor.
        2. Most dependencies are private, not meant to be exposed in a public API (the annotated constructor). For example, a DAO, or a JPA EntityManager. Having only the field for each such dependency (rather than the field + the constructor parameter) is simpler, takes less code, and preserves encapsulation which would otherwise be broken by exposing the dependency through a public constructor.
        3. Java EE has made the choice of prefering field injection, with constructor/setter injection being supported only as an afterthought. From my experience, most new projects nowadays and in the future will be using Java EE instead of Spring.

        • Petri Oct 30, 2015 @ 20:00

          Interesting comment. Here are my thoughts about this:

          Constructor injection requires more code: you need to have instance fields for the injected dependencies, and also an assignment to each field in the injection constructor.

          True, but this is a good thing.

          Most dependencies are private, not meant to be exposed in a public API (the annotated constructor). For example, a DAO, or a JPA EntityManager.

          You can define a public API by using interfaces and hiding the actual implementations.

          Having only the field for each such dependency (rather than the field + the constructor parameter) is simpler, takes less code, and preserves encapsulation which would otherwise be broken by exposing the dependency through a public constructor.

          So, what happens if you remove the bean that is required by another bean? The field injection doesn't really encapsulate anything. The only thing that happens is that the dependencies of the created bean are hidden (but still required). If you really want to encapsulate the implementation details of a bean, you should use interfaces (but only if you have more than one implementation OR you want to publish the API of a module).

          Java EE has made the choice of prefering field injection, with constructor/setter injection being supported only as an afterthought. From my experience, most new projects nowadays and in the future will be using Java EE instead of Spring.

          This constructor injection vs. field injection discussion has got nothing to do with Java EE or Spring. I think it is great that Java EE works for you. Keep using it.

    • srini Dec 4, 2014 @ 19:37

      thanks for your suggestions,
      my controller method and agruments are same which i am trying to set in mockito.when -exceptation.
      i will try your suggestion instead of inject mock i will try to set using ReflectionTestUtil.setField() method and come back
      one more question i debugged mockito api it is not stubbing utils class, -is this due to util class has also some autowire components

      • Petri Dec 4, 2014 @ 20:28

        Do you create a new MyController object in your test class? The reason why I am asking this is that your sample code does not create it.

        If you use the @InjectMocks annotation, you have to use it as follows:

        
        @InjectMocks
        private final MyController mycont = new MyController();
        
        

        one more question i debugged mockito api it is not stubbing utils class, -is this due to util class has also some autowire components

        Unfortunately it is impossible to say what is wrong without seeing the source code of the tested controller and the MyUtil class. However, I think that the dependencies of the MyUtil class have got nothing to do with this problem because I have been able to mock classes that use other components.

    • srini Dec 9, 2014 @ 13:39

      how to mock service method having request as argument in the controller.

      i used the mockmvc with test class is annoted with @mokitojunitrunner as advised in tutorial
      mokito always returns false because in mockmvc framework ,it creates MockHttpServletRequest but actual service method has HttpServletRequest due to this mismatch in object type -i debugged the findout the above reason .
      could you please suggest how to deal with this..

      • Petri Dec 9, 2014 @ 18:01

        Hi,

        Here is a little example that demonstrates how you can solve your problem.

        First, my controller looks as follows:

        
        @RestController
        @RequestMapping("/api/hello")
        final class HelloController {
        
            private final HelloService service;
        
            @Autowired
            public HelloController(HelloService service) {
                this.service = service;
            }
        
            @RequestMapping(method = RequestMethod.GET)
            String hello(HttpServletRequest request) {
                return service.hello(request);
            }
        }
        
        

        Second, my service class looks as follows:

        
        @Service
        public class HelloService {
        
            public String hello(HttpServletRequest request) {
                return "hello";
            }
        }
        
        

        And my passing test looks as follows:

        
        @RunWith(MockitoJUnitRunner.class)
        public class HelloControllerTest {
        
            @Mock
            private HelloService service;
        
            private MockMvc mockMvc;
        
            @Before
            public void setUp() {
                mockMvc = MockMvcBuilders.standaloneSetup(new HelloController(service))
                        .build();
            }
        
            @Test
            public void hello_ShouldReturnHello() throws Exception {
        		//Mock the service method
                when(service.hello(isA(HttpServletRequest.class))).thenReturn("FOOBAR");
        
                mockMvc.perform(get("/api/hello"))
                        .andExpect(content().string("FOOBAR"));
            }
        }
        
        

        I hope that this answered to your question. If not, feel free to ask additional questions.

  • yaowei Jan 22, 2015 @ 14:09

    thank you and really appreciate

    • Petri Jan 22, 2015 @ 20:33

      You are welcome! I am happy to hear that this tutorial was useful to you.

  • Anonymous Feb 28, 2015 @ 10:00

    Hi Petri,

    Your blog is awesome and providing good amount of unit and integration testing.

    • Petri Mar 1, 2015 @ 10:08

      Thank you for your kind words! I really appreciate them.

  • matt Mar 2, 2015 @ 10:57

    Hello, Petri.
    Nice tutorial, but what should I do if I have an @ImportResource annotation in my Controller (for example @ImportResource("classpath:controllerContext.xml") where controllerContext.xml contains the same context as I use in testing) ? Everything is ok if I've got it, tests work nice, but when I delete it, tests do not pass due to
    java.lang.AssertionError: Content type not set
    at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:39)
    My controller needs @ImportResource to get configuration, without it I've got
    org.springframework.beans.factory.BeanCreationException
    Thanks.

    • Petri Mar 4, 2015 @ 20:40

      Why you added the @ImportResource annotation to your controller class instead of your application context configuration class? The reason why I ask this is that typically that annotation is used to import XML configuration files from application context configuration classes (@Configuration classes).

      Unfortunately it is kind of hard to give you a better answer without seeing your code, but it seems that the problem is somehow related to the way you configure your application / tests. If you can share your application context configuration classes, XML configuration files, and your test class, I can probably give you a better answer.

  • Johan Apr 8, 2015 @ 23:53

    Hi Petri,

    Thank you for this truly outstanding article. And the followup looks even better! Will have continue studying that one soon.

    I am relatively new with Spring and Spring MVC (somewhat less with Java, but still..), so please don't shoot me if this is a stupid question.

    You explained how to setup the test context config using the standalone configuration and reusing (part of) the "production" WebApplicationContext.

    Now, in a test project I had configured a service bean, used by 2 controllers. This bean is defined in my WebConfig (WebMvcConfigurerAdapter) class (maybe that's not a good idea?).

    As I wanted to use a mock version of those services, I was thinking of a way to solve this and I came up with a variation on your idea to point to both the existing WebConfig and an additional test config.

    It looks like this:

    • in the test classes I don't refer to the existing WebConfig, but to a TestContext class @ContextConfiguration(classes=TestContext.class)
    • this TestContext class extends the existing WebConfig and overrides the service bean with a mock version.
    
    @Configuration
    public class TestContext extends WebConfig
    {
         @Bean
        @Override
        public ProductManager productManager() {
            return Mockito.mock(ProductManager.class);
        }
    }
    
    

    My tests seems to be working fine.

    Do you think this an acceptable approach?

    Thank you for your reply.

    Best regards,
    Johan

    I changed the formatting a bit so that your question looks "better" - Petri

    • Petri Apr 9, 2015 @ 0:30

      Hi Johan,

      Thank you for your kind words. I really appreciate them!

      If you want to use the WebApplicationContext based setup, I recommend that you divide your application configuration context configuration in a such way that the @Configuration class which configures the web layer configures only the beans that belong to the web layer.

      If you don't do this, replacing the service beans with mocks becomes a bit "messy". In your case this is not a huge problem because you can extend the WebConfig class and override its @Bean methods. However, if you would have used the @ComponentScan annotation to scan the service beans, you would be in trouble.

      In other words, you might want to use the following setup:

      • The WebConfig class configures only the web layer.
      • The ServiceConfig class (awful name, don't use this) class configures the service beans.
      • The TestServiceConfig class configures the required mock service beans.

      Now you can create a simple application context configuration class that looks as follows:

      
      @Configuration
      @Import({TestServiceConfig.class, WebConfig.class})
      public class TestContext {
      }
      
      

      As you can see, this class simply imports the required application context configuration classes and you are good to go. What do you think about this approach?

      Also, I don't use the WebApplicationContext based setup in my unit tests anymore. I realized that creating mock beans becomes pain in the ass if you have to mock "many" service beans. If you use the WebApplicationContext based setup, you have to remember to add your mock beans to the TestServiceConfig class or your tests will fail.

      That is why I use standalone configuration for unit tests and WebApplicationContext based configuration for integration tests.

      • Johan Apr 9, 2015 @ 21:17

        Hi Petri,

        Thank you very much for your answer, which makes more than a lot of sense.
        I will certainly take your advice at heart in order to avoid any unnecessary pain in the ass. ;-)

        I wish I had more time to investigate your blog, you seem to procure mind blowing articles!
        ...well, maybe one article a day... ;-)

        Thanks again and best regards,

        • Petri Apr 9, 2015 @ 22:56

          Hi Johan,

          You are welcome. I am happy to hear that my answer was useful to you. Also, if you have any other questions, don't hesitate to ask them.

          All the best.

  • Luis May 22, 2015 @ 22:33

    Hi, have a good day.

    I have a project that uses xhtml files i meke a war file, but i don't use spring, i use jsf. I would like to know if i can use your example to test my project.

    Thanks!!

  • jadhav prashant Jun 12, 2015 @ 8:47

    hey i got error on TodoService in TodoController class please resolve it sir

  • peter Jun 12, 2015 @ 16:17

    getting null pointer exception at

    
    mockMvc.perform(MockMvcRequestBuilders.get("/Login"))
    	.andExpect(status().isOk())
    	.andExpect(view().name("Login"))
    	.andExpect(forwardedUrl("/WEB-INF/pages/Login.jsp"));
    
    
    • Petri Jun 12, 2015 @ 19:56

      Did you create the mockMvc object by using application context based configuration or standalone configuration? Also, are you sure that it is not null?

      If the mockMvc object is not null, you can the print the response (and the other relevant information) by using this code:

      
      mockMvc.perform(MockMvcRequestBuilders.get(“/Login”))
      	.andDo(print());
      
      

      This should help you to solve your problem.

      • peter Jun 15, 2015 @ 7:24

        hello petri,
        Thank you for your replay but still I get the same eexception, yes I have created my mockMvc object ,Im very new to this concept I defenately know that I have missed something important, but not able to trace it out, and also please tell me that how can I know that mock object is null or not null
        waiting for your response
        Thanks

        private MockMvc mockMvc;
        public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
        }

        • Petri Jun 16, 2015 @ 20:40

          Can I see the stacktrace? I don't know why your test throws NPE, and I suspect that the stacktrace could help me to figure out what is going on.

          • Govardhan reddy Jun 30, 2015 @ 10:33

            Hi Petri,
            Your way of explanation is good , but
            The first application configuration class is called ExampleApplicationContext and it is the “main” configuration class of our application.

            The third configuration class is called PersistenceContext and it contains the persistence configuration of our application.
            I have doubt about above two sentences
            Where is the source code about ExampleApplicationContext and PersistenceContext

          • Petri Jun 30, 2015 @ 10:47
  • ArunM Jul 29, 2015 @ 9:25

    Hi Petri,

    Thanks for the brilliant tutorial. In addition to learning more about Spring MVC testing, this blog has helped to learn more about the user of Mockito and Hamcrest as well.

    Regards,
    ArunM

    • Petri Jul 29, 2015 @ 14:09

      You are welcome! I am happy to hear that my Spring MVC Test tutorial was useful to you.

  • Ankit Sep 1, 2015 @ 9:51

    getting problem while testing and the error is autowiring dependency injection problem for the test class I wrote.......

    provide some solution.....
    thankyou

    • Petri Sep 1, 2015 @ 11:22

      I need to see the stack trace before I can figure out what is wrong. Can you add it into a new comment?

  • Gaetano Oct 8, 2015 @ 16:12

    Hi Petri,

    I'm trying to test my controller using the Standalone approach but I'm struggling injecting MessageSource.

    In my case the controller does not use "constructor injection". MessageSource is injected via setter injection.

    my controller looks like:

    
    @Controller
    public class MyController {
    	@Autowired
    	private WebUserService webUserService;
    	
    	@Autowired
    	private MessageSource messageSource;
    
    }
    
    
    • Anonymous Oct 8, 2015 @ 16:14

      ...sorry I hit submit by mistake
      anyway how my standalone test configuration should be in order to inject the MessageSource ?

      Thanks
      Gaetano

      • Petri Oct 8, 2015 @ 16:38

        Hi,

        If you use setter injection, you can simple create the controller object and invoke the correct setter. The setUp() method, which uses this approach, looks as follows:

        
        @Before
        public void setUp() {
        	MessageSource messageSource = ... //create MessageSource
        	TestedController controller = new TestedController();
        	controller.setMessageSource(messageSource)
        		
        	mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
        }
        
        

        However, the code you pasted uses field injection. In this case you need to "inject" the MessageSource object by using a utility class called ReflectionTestUtils. The setUp() method, which injects the MessageSource object by using that utility class, looks as follows:

        
        @Before
        public void setUp() {
        	MessageSource messageSource = ... //create MessageSource
        	TestedController controller = new TestedController();
        	ReflectionTestUtils.setField(controller, "messageSource", messageSource);
        		
        	mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
        }
        
        

        If you have any additional questions, don't hesitate to ask them.

        • Gaetano Oct 8, 2015 @ 17:19

          Hi Petri,
          Thanks a lot for your help - it worked
          You might hear from me in a couple of days, when I'll try to tackle the approach based on WebApplicationContext :)
          Regards
          Gaetano

          • Petri Oct 8, 2015 @ 19:47

            You are welcome! Also, it will be fun to see what I forgot to mention in this rather old blog post ;)

  • Nitesh Kumar N Apr 1, 2016 @ 11:04

    how to overcome the circular view path exception, because I have my uri and the return type string are the same.
    @RequestMapping(value = "newemployee", method = RequestMethod.GET)
    public ModelAndView newEmployeeGet(HttpServletRequest request) {
    String ss = "[\"1-1-2016\",\"2-1-2016\",\"3-1-2016\",\"4-1-2016\",\"5-1-2016\",\"6-1-2016\",\"7-1-2016\",\"8-1-2016\"]";
    map.put("holidays", ss.toString());
    return new ModelAndView(prefixResult + "newemployee", map);
    }

    cannot be changing the methods now. But I have to do something to get rid of this circular view path exception. How do I do it.

    • Petri Apr 1, 2016 @ 19:11

      Check out this StackOverflow answer. It provides a good description of this problem.

      Unfortunately I am not sure how you can fix this because I am not sure what you want to do. Do you want to redirect the request to another controller method or do you simple want to render a view? If you want to render a view, what view technology are you using?

  • Prakash Boda Jun 9, 2016 @ 18:41

    Hi Petri,

    I found your post very useful. I am trying to test my REST APIs using Spring test + Mockito as you suggested. I am trying using standAloneSetup method. But some of my DTO classes have date field and for same I am using JSON serializer for converting it into my desired format. Usually this format comes from our properties file and I have fetched format from properties file as below.
    public class CustomDateSerializer
    extends JsonSerializer {
    @Value("${dateFormat}")
    private String dateFormat;
    @Value("${timeFormat}")
    private String timeFormat;

    so in run time it gets properties file in class path fetches format properly but while running test it is not able fetch OR may be expression is not even getting evaluated so its getting format fields null and it fails request to status 500.

    How can I resolve this issue?

    • Petri Jun 13, 2016 @ 13:49

      Hi,

      Have you configured the MappingJackson2HttpMessageConverter object and provided it to the created MockMvc object? If you haven't done this, you should give it a shot. If you don't know how you configure the MappingJackson2HttpMessageConverter object, take a look at this blog post.

  • Java Servlet Tutorial Sep 13, 2016 @ 19:51

    Great tutorial, keep going on!

    • Petri Sep 19, 2016 @ 18:26

      Thanks!

  • Stone B Apr 14, 2017 @ 14:28

    Hello There,

    Great tutorial!
    I am curious why did you strike through MockitoJUnitRunner

    • Petri Apr 15, 2017 @ 0:10

      Hi,

      I use a plugin that identifies dead links and marks them as dead. I assume that this plugin added the strike though "style" to the link because the website was down when it checked the link.

  • yuxh Apr 27, 2017 @ 7:55

    hi,Petri,I see someone said "Even if you’re just using the Spring Context to auto-wire dependencies, your test is an integration test" in https://springframework.guru/mockito-mock-vs-spy-in-spring-boot-tests/ .
    so I think the adoption of standaloneSetup or webAppContextSetup method can be see as integration test, what's your opinion?

    • Petri May 19, 2017 @ 18:50

      Hi,

      The difference between the application context based configuration and the standalone configuration is that if you use the standalone configuration, you can use only the components that are relevant for the test case. In other words, the standalone configuration helps you to minimize the size of the tested unit.

      If you think about the traditional definitions of unit and integration testing, a test that uses Spring MVC Test framework is not a unit test because you are not testing the controller method in isolation. However, I don't use the web application context based setup in my "unit tests" anymore because the standalone setup helps me to highlight the dependencies of the system under test.

      P.S. I use the terms integration and unit tests mainly because they are more familiar than terms slow and fast tests (although the latter terms are better IMO).

  • Govar May 16, 2017 @ 22:43

    Thanks Petri...This is very useful!

    • Petri May 19, 2017 @ 18:42

      You are welcome!

  • FransAsian Jun 1, 2017 @ 20:19

    Thank you man, God bless you for sharing knowledge...

    • Petri Jun 1, 2017 @ 23:35

      You are welcome!

  • Fred Jul 26, 2017 @ 12:11

    Do you know that some of the code samples on this range of tutorial pages have incorrect escaping? For example:

    &lt;dependency&gt;
    &lt;groupId&gt;junit&lt;/groupId&gt;
    &lt;artifactId&gt;junit&lt;/artifactId&gt;
    &lt;version&gt;4.11&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;

    It makes it a bit more difficult to follow.

    • Petri Jul 26, 2017 @ 13:08

      Nope. I wasn't aware of that. It's fixed now. I have to check what's causing this because it seems that this behavior is totally random. I guess that some WP plugin is not working correctly. In any case, thank you for reporting this issue.

  • Satheeshkumar Oct 4, 2019 @ 9:54

    Hi,
    What is the use of TodoDTO.java

    • Petri Oct 5, 2019 @ 19:54

      Hi,

      The TodoDTO class is a data transfer object which helps us to hide the internal data model of our application from the outside world.

Leave a Reply