Spring Boot 2.x Basic Tutorial: Building RESTful API s and Unit Testing

Posted by Crowly on Sat, 28 Sep 2019 18:05:59 +0200

First, review and elaborate on quick get start The @Controller, @RestController, @RequestMapping annotations used in the.If you are unfamiliar with Spring MVC and have not tried the Quick Start case, it is recommended that you take a look first quick get start Content.

  • @Controller: Decorates the class to create an object that handles http requests
  • Annotations added after @RestController:Spring4, originally returning json in @Controller requires @ResponseBody to work with. If @RestController is used directly instead of @Controller, the @ResponseBody will no longer need to be configured and json format will be returned by default
  • @RequestMapping: Configure url mappings.More will now be defined directly with mapping annotations directly associated with the Http Method, such as GetMapping, PostMapping, DeleteMapping, PutMapping, and so on.

Here we implement a set of RESTful API s for manipulating User objects using Spring MVC, with comments detailing how HTTP requests are mapped, how parameters are passed, and how unit tests are written in Spring MVC.

The RESTful API is specifically designed as follows:

Define User Entities

@Data
public class User {

    private Long id;
    private String name;
    private Integer age;

}

Note: Compare 1.x version of the tutorial Use the @Data annotation to automatically add set and get functions to the compiler.This annotation is provided by lombok and can be supported by simply adding the following dependencies into the pom:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

Implement an interface for manipulating User objects

@RestController
@RequestMapping(value = "/users")     // Configure here so that the following maps are all under / users
public class UserController {

    // Create a thread-safe Map that simulates the storage of users information
    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());

    /**
     * Processing GET request for'/users/'to get a list of users
     *
     * @return
     */
    @GetMapping("/")
    public List<User> getUserList() {
        // You can also pass parameters from a page through @RequestParam to transfer query criteria or paging information
        List<User> r = new ArrayList<User>(users.values());
        return r;
    }

    /**
     * Processing POST request for'/users/'to create User
     *
     * @param user
     * @return
     */
    @PostMapping("/")
    public String postUser(@RequestBody User user) {
        // The @RequestBody annotation is used to bind data uploaded through the application/json type in http requests
        users.put(user.getId(), user);
        return "success";
    }

    /**
     * Processing GET request for'/users/{id}'to obtain User information for ID values in url
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        // IDS in URLs can be bound to parameters of functions through @PathVariable
        return users.get(id);
    }

    /**
     * Process a PUT request for'/users/{id}'to update User information
     *
     * @param id
     * @param user
     * @return
     */
    @PutMapping("/{id}")
    public String putUser(@PathVariable Long id, @RequestBody User user) {
        User u = users.get(id);
        u.setName(user.getName());
        u.setAge(user.getAge());
        users.put(id, u);
        return "success";
    }

    /**
     * Processing DELETE request for'/users/{id}'to delete User
     *
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public String deleteUser(@PathVariable Long id) {
        users.remove(id);
        return "success";
    }

}

Compare here 1.x version of the tutorial In, the previous @RequestMaping annotation is replaced with a more detailed series of @GetMapping, @PostMapping annotations; in addition, the parameter bindings of @ModelAttribute are replaced with @RequestBody.

Write unit tests

The following test cases are written for this Controller to verify correctness, as follows.Of course, Request Submission verification can also be done through browser plug-ins, etc.

@RunWith(SpringRunner.class)
@SpringBootTest
public class Chapter21ApplicationTests {

    private MockMvc mvc;

    @Before
    public void setUp() {
        mvc = MockMvcBuilders.standaloneSetup(new UserController()).build();
    }

    @Test
    public void testUserController() throws Exception {
        // Test UserController
        RequestBuilder request;

        // 1. get checks the list of user s and should be empty
        request = get("/users/");
        mvc.perform(request)
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("[]")));

        // 2. post submits a user
        request = post("/users/")
                .contentType(MediaType.APPLICATION_JSON)
                .content("{\"id\":1,\"name\":\"Test Master\",\"age\":20}");
        mvc.perform(request)
                .andExpect(content().string(equalTo("success")));

        // 3. get get a list of user s, there should be data just inserted
        request = get("/users/");
        mvc.perform(request)
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("[{\"id\":1,\"name\":\"Test Master\",\"age\":20}]")));

        // 4. user whose put modifies id 1
        request = put("/users/1")
                .contentType(MediaType.APPLICATION_JSON)
                .content("{\"name\":\"Test Ultimate\",\"age\":30}");
        mvc.perform(request)
                .andExpect(content().string(equalTo("success")));

        // 5. get a user with id 1
        request = get("/users/1");
        mvc.perform(request)
                .andExpect(content().string(equalTo("{\"id\":1,\"name\":\"Test Ultimate\",\"age\":30}")));

        // 6. Delete user with id 1
        request = delete("/users/1");
        mvc.perform(request)
                .andExpect(content().string(equalTo("success")));

        // 7. get checks the list of user s and should be empty
        request = get("/users/");
        mvc.perform(request)
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("[]")));

    }

}

Readers unfamiliar with MockMvc may encounter functions that do not exist and fail.References to these static functions must be introduced:

import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

Compare here 1.x version of the tutorial There are two main differences.The test class is started with @RunWith(SpringRunner.class) and @SpringBootTest modifications; in addition, since the parameters of the POST and PUT interfaces are annotated with @RequestBody, the submission will be a json string instead of the previous parameter form, where contentType(MediaType.APPLICATION_JSON) is used when defining the requestFixed submissions are in json format, and content is used to pass in a json string to submit.If you use @ModelAttribute, you have to add parameters using the param method, as you can see 1.x version of the tutorial.

So far, by introducing a web module (without any other configuration), we can easily take advantage of Spring MVC's capabilities to create a RESTful API for User objects and write unit tests in very simple code.Several of the most common core annotations in Spring MVC are also described: @RestController,RequestMapping, and annotations for some parameter bindings: @PathVariable,@RequestBody, etc.

Code Samples

Examples of this article can be found in the chapter2-1 catalog in the following repositories:

If you think this is a good article, welcome to Star Support, your attention is my motivation!

Welcome to my public number, Programmed Ape DD, for exclusive learning resources and daily dry delivery.If you are interested in my topic, you can also follow my blog: didispace.com

Topics: Java JSON Spring Lombok github