Want to see Parasoft in action? Sign up for our Monthly Demos! See Demos & Events >>

X
BLOG

Start to Love Spring Testing With the Unit Test Assistant for Java

Start to Love Spring Testing With the Unit Test Assistant for Java Reading Time: 7 minutes
Spring is the leading enterprise Java application framework and as such needs an appropriate level of testing to ensure the quality and security of applications built with it.

The Spring framework (along with Spring Boot) is one of the most popular Java enterprise software frameworks. Its use in mission-critical applications means it has come under scrutiny for quality and security.

Previously, our VP of Products Mark Lambert discussed how developers don’t like unit testing despite its proven track record of improvement, and detailed how Parasoft Jtest’s Unit Test Assistant can provide a guided and automated approach to testing to make testing not only more palatable, but also easier and more efficient. In this post, I’ll continue the same theme with the Spring framework, showing you unit test examples and how automated and guided testing can be leveraged in this important application framework.

The Challenges of Testing Spring Applications

The Spring framework comes with nice support for integration testing, but a lot of manual coding is required to set up test cases properly. Building and maintaining tests for Spring applications presents developers with a unique set of challenges, including the following:

  • The Spring framework must be initialized and configured
  • The application usually has 3rd-party library dependencies (persistent storage, external services, etc.)
  • Applications often use built-in Spring features for sessions, security, messaging, etc. These can be tricky to set up for developers who are new to Spring testing
  • Application dependencies (i.e. beans) need to be configured appropriately

These challenges, combined with the fact that writing comprehensive and maintainable test suites takes a lot of time in general, result in developers not writing enough tests In turn, this leads to security vulnerabilities, defects, regressions, and lots of headaches.

The Parasoft Jtest Unit Test Assistant helps by making the process of generating, improving, and maintaining JUnit tests far easier and less time-consuming, so that developers build good tests quickly and get back to what they presumably love – writing code.

Accelerate Unit Testing of Spring Applications With Parasoft Jtest and its Unit Test Assistant

The Spring MVC Test Framework

The Spring Framework includes a testing framework that makes testing Controllers, Services, and other components much easier. It includes functionality for configuring the Spring test container, invoking Controller handler methods, and validating behavior with custom assertions.

An example Spring MVC Controller:

@Controller
public class TodoController {     @Autowired
    private TodoService service;
    @GetMapping("/")    public String findAll(Model model) {
        List<Todo> todos = service.findAll();
        model.addAttribute("todos", todos);
        return "todo/list";
    }
}

This example controller implements a simple REST service to get items from a “to-do” list. It depends on a TodoService, which contains the business logic.

To test the findAll method, we need a JUnit test which does the following:

  • Configure the Spring container with the Controller under test, and a TodoService, which TodoController depends on.
  • Send a valid request to the findAll handler method.
  • Validate elements of the response, including the return value (“todo/list”) and Model attribute “todos”.

An example Spring MVC Junit test may look like this:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class TodoControllerTest {
    @Autowired
    TodoController controller;
 
    @Autowired
    TodoService todoService;
 
    MockMvc mockMvc;
 
    @Before
    public void setup() {
        mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
    }
 
    @Configuration
    static class Config {
        @Bean
        public TodoController getTodoController() {
            return new TodoController();
        }
 
        @Bean
        public TodoService getTodoService() {
            return new TodoService();
        }
    }
 
    @Test
    public void testFindAll() throws Exception {
        mockMvc.perform(get("/")).andExpect(view().name("todo/list"));
    }
}

The above example is a very simple test – but there’s still a lot of “boiler-plate” code to write, and a lot going on. In this example, we have configured Spring with a controller and its services, using an inner Configuration class. We then use the MockMvc functions to send a request to the handler method (using perform), and validate the returned view name using andExpect.

What’s wrong with the above test? Nothing really – but imagine a more complex controller method, with multiple handler methods that accept more arguments and produce more outputs. Writing the tests would take a lot more time, especially if good testing coverage is important. In addition, most real tests require significantly more configuration (XML or class configurations, sessions and environments, security, etc).

Generating Spring Tests with Parasoft Jtest

Parasoft Jtest’s Unit Test Assistant helps developers write Spring tests in multiple ways:

  1. Auto-generating the boiler-plate code for Spring MVC tests quickly
  2. Auto-generating parameterized tests for increased test coverage
  3. Mocking dependencies to isolate the helper method and simplify the test
  4. Collecting coverage data and analyzing test flow at runtime
  5. Providing recommendations with quick-fixes to improve tests

Auto-Generating Tests

Generating Spring tests in Parasoft Jtest is straightforward – simply select a Spring handler method in your IDE for your controller and choose a test-creation action:

Start to Love Spring Testing With the Unit Test Assistant for Java

Choosing either Regular Spring or Parameterized Spring auto-generates the boiler-plate Spring MVC test for you, including the Configuration classes (and all Beans that your controller depends on). The mockMvc.perform call is added too, and is preconfigured to invoke the handler method for which the test was created. The Jtest Unit Test Assistant even adds some example assertions that you can uncomment and configure.

Parasoft Jtest supports test generation using XML or class configuration by setting the “ContextConfiguration attributes for Spring tests” option in preferences.

Mocking Dependencies

Managing dependencies in unit testing is critical, since much of the complexity and work comes from isolating a unit under test. The Jtest Unit Test Assistant uses Mockito or PowerMockito to mock dependencies by default (you can disable this in preferences if you don’t want this). Mocking dependencies allows the test to control those dependencies, isolating the handler method from the rest of the application to focus testing efforts on the handler. In our example handler, the findAll method was invoked on TodoService – if we use a real TodoService, we are effectively testing both the TodoController and the TodoService. This may be what we want for an integration test, but not for a unit test. Mocking the response of TodoService.findAll in the test allows us to focus our testing efforts on the handler method.

(If you want more info about mocking dependencies in Spring tests, read on to my next post.)

Ebook: Improve Unit Testing for Java With Automation

Spring Boot

Since Spring Boot provides simplified configuration for Beans, as well as additional annotations for tests, the Unit Test Assistant generates slightly different tests when it detects Spring Boot in your project. For example, MockMvc is autowired, dependencies are mocked with @MockBean, and the @SpringBootTest annotation is used.

Running Tests and Analyzing Results

You can run generated tests using any normal JUnit runner. Parasoft Jtest provides toolbar actions that run the JUnit and analyze the test.

Start to Love Spring Testing With the Unit Test Assistant for Java

After tests are run, the test execution flow is shown, and recommendations for improving the test are made by the Unit Test Assistant and reported in your IDE:

Start to Love Spring Testing With the Unit Test Assistant for Java

Providing Handler Method Inputs

Handler methods are often configured to accept path, query, or other parameters as arguments to the method. To test the MVC handler method, you can use MockMvc to build the path/query and any other parameters needed to invoke the method.

The Jtest Unit Test Assistant auto-configures the mockMvc.perform call to invoke the handler method. Individual parameters show up in the test as local variables (or parameters in a parameterized test) which need to be configured for the test to run properly.

For example (see Unit Test Assistant abbreviated as UTA below):

@Test public void testGetPerson() throws Throwable {     // When     String id = ""; // UTA: Configure an appropriate parameter value since the tested method depends on it     ResultActions actions = mockMvc.perform(get("/people/" + id));

Here, the “id” String needs to be configured – if not, then the path used would be “/people/”, and Spring will not match the provided path to the appropriate handler method.

class=”p1″>The Unit Test Assistant looks for various types of handler method parameters and automatically prepares the test for them in the following ways:

  • HttpSession (adds an example setAttribute() call)
  • Headers (adds a header() call),
  • Request body (adds a payload variable and content() call)
  • Authentication (adds an example instantiation to the setup method, and a principal() call)

Running a test which does not cause the handler method to be invoked produces a recommendation like the following:

Start to Love Spring Testing With the Unit Test Assistant for Java

Validating Handler Method Outputs

Depending on what the handler method is supposed to provide to callers, it may return a variety of types. Most of the time, handler methods return either a ModelAndView (or similar objects like Model or RedirectView) to serve a page, or a ResponseEntity of some kind (sometimes just the raw object to be serialized). This response is accessible to the Spring MVC Test framework for validation.

For example, the following assertions were added by the Jtest Unit Test Assistant for a handler method which returns a ModelAndView:

  // When
  String id = "1";
  ResultActions actions = mockMvc.perform(get("/people/" + id));
 
  // Then
  // actions.andExpect(status().isOk());
  // actions.andExpect(header().string("", ""));
  // actions.andExpect(view().name(""));
  // actions.andExpect(model().attribute("", ""));

Once the test is generated, you can uncomment these assertions and populate values to quickly build a useful and valuable test. If an assertion fails at runtime, the Unit Test Assistant provides a recommendation and quick-fix to automatically update the expected value or simply remove the assertion. To quickly set up the assertion with a proper value, you can uncomment an assertion, let it fail, and then use a quick-fix to set the correct expected value.

To Conclude

Spring (combined with Spring Boot) is the leading enterprise Java application framework and as such needs an appropriate level of testing to ensure the quality and security of applications built with it. But unfortunately, this level of testing is not being achieved currently, mostly due to a lack of time and the amount of manual coding and maintenance required. The Parasoft Jtest Unit Test Assistant provides not just unit test automation but guided test creation and dependency management, to accelerate test creation and reduce maintenance.

To learn more, read how the Unit Test Assistant can help with dependency management with mocking frameworks.

Learn how to increase your return from unit testing with Parasoft Jtest.
Request a Demo Now
Written by

Brian McGlauflin

Brian McGlauflin is a software engineer at Parasoft with experience in full stack development using Spring and Android, API testing, and service virtualization. He is currently focused on automated software testing for Java applications with Parasoft Jtest.

将最新的软件测试新闻和资源发送到您的电子邮箱。