Dependency injection should make the code less dependent on the container than it would be with traditional Java EE development. The POJOs that make up your application must be testable in JUnit or TestNG along with objects instantiated using the new operator, without the involvement of Spring or any other container. You can use mock objects (in combination with other useful testing techniques) to test your code in isolation. If you follow the Spring architecture guidelines, the resulting clean, layered and componentized view of the codebase will make unit testing easier. For example, you can test service-layer objects using a stub function or mock object for DAO or storage interfaces, without having to access persistent data while running unit tests.

True unit tests are usually extremely fast because there is no need to create a runtime infrastructure. Emphasizing true unit tests as part of the development methodology can improve productivity. You may not need this section of the testing chapter to write effective unit tests for your IoC-based applications. However, for certain unit testing scenarios, the Spring Framework provides mock objects and test helper classes, which are covered in this chapter.

Imitation object

Spring has a number of packages designed to use mock objects:

  • Wednesday

  • JNDI

  • Servlet API

  • Web Reactive module in Spring

Environment

The org.springframework.mock.env package contains mock implementations of the Environment and PropertySource abstractions (see "Bean definition profiles" and "Abstraction PropertySource"). MockEnvironment and MockPropertySource are useful for developing container-free tests for code that depends on environment-specific properties.

JNDI

The org.springframework.mock.jndi package contains a partial implementation of the JNDI SPI interface that can be used to create a simple JNDI framework for test suites or standalone applications. If, for example, DataSource instances from JDBC are bound to the same JNDI names in the test code as in the Java EE container, then both application code and configuration can be reused in test scripts without modification.

Support for JNDI mock objects in the org.springframework.mock.jndi package has been officially deprecated since Spring Framework 5.2, in favor of ready-made solutions from third party developers such as Simple-JNDI.

Servlet API

The org.springframework.mock.web package contains a complete set of Servlet API mock objects that are useful for testing web contexts, controllers, and filters. These mock objects are designed for use with the Spring Web MVC framework and are generally more user-friendly than dynamic mock objects (for example, EasyMock) or alternative Servlet API mock objects (for example, MockObjects).

Starting with Spring Framework 5.0, mock objects in org.springframework.mock.web are based on the Servlet API 4.0.

The Spring MVC Test framework is based on Servlet API mock objects, which provides an integration testing framework for Spring MVC. See "MockMvc".

Web Reactive module in Spring

The org.springframework.mock.http.server.reactive package contains mock implementations of ServerHttpRequest and ServerHttpResponse for use in WebFlux applications. The org.springframework.mock.web.server package contains a ServerWebExchange mock object that depends on these mock request and response objects.

Both MockServerHttpRequest and MockServerHttpResponse come from the same abstract base classes as the server-specific implementations, and share common logic with them. For example, a mock request object is not replaceable once created, but you can use the mutate() method of ServerHttpRequest to create a modified instance.

In order for the mock response object to correctly implement the write contract and return a write completion handle (that is, Mono<Void>), it defaults to Flux with cache().then(), which buffers data and makes it available for assertions in tests. Applications can install a special recording function (for example, to check for an infinite thread).

WebTestClient is based on a simulated request object and response object and provides support for testing WebFlux applications without HTTP -servers. The client part can also be used for end-to-end testing with a running server.

Helper classes for unit testing

Spring contains a number of classes that can help with unit testing. They are divided into two categories:

  • General purpose testing utilities

  • Utilities for testing in Spring MVC

General purpose testing utilities

The org.springframework.test.util package contains several general-purpose utilities for use in unit and integration testing.

ReflectionTestUtils is a collection of utility methods based on reflection. You can use these methods in test scripts when you need to change the value of a constant, set a non-public field, call a non-public setter, or call a non-public code> configuration or lifecycle callback method when testing application code in the following cases:

  • ORM frameworks (such as JPA and Hibernate) that allow private or protected access to fields, as opposed to public property setters in the essence of the subject area.

  • Support for Spring annotations (such as @Autowired, @Inject and @Resource), which provide dependency injection for private or protected fields, setters and configuration methods.

  • Use annotations such as @PostConstruct and @PreDestroy for lifecycle callback methods.

AopTestUtils is a collection of AOP-related utility methods. You can use these methods to obtain a reference to an underlying target hidden behind one or more Spring proxies. For example, if you have configured a bean as a dynamic mock object using a library such as EasyMock or Mockito, and that mock object is wrapped in a Spring proxy, you may need to directly access the underlying mock object to configure expected events for it and perform the check. For information about the main AOP utilities in Spring, see the topics on AopUtils and AopProxyUtils.

Utilities for testing in Spring MVC

Package org.springframework.test.web contains ModelAndViewAssert which you can use in combination with JUnit, TestNG or any other testing framework for unit tests working with ModelAndView objects from Spring MVC.

To unit test Controller classes from Spring MVC as POJOs, use ModelAndViewAssert in combination with MockHttpServletRequest , MockHttpSession, etc. from among the Servlet API mock objects. To perform thorough integration testing of Controller classes from Spring MVC and REST in combination with the WebApplicationContext configuration for Spring MVC, use the Spring MVC Test Framework.