当前位置: 首页 > 知识库问答 >
问题:

Spring启动:MockMvc返回奇怪的响应

司马庆
2023-03-14

我有以下控制器:

重启控制器。爪哇

package com.spring.ocr.rest.restconsume.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;

import com.spring.ocr.rest.restconsume.model.User;
import com.spring.ocr.rest.restconsume.service.UserService;
import com.spring.ocr.rest.restconsume.util.CustomErrorType;

@RestController
@RequestMapping("/api")
public class RestApiController {

    @Autowired
    UserService userService;

    @RequestMapping(method = RequestMethod.GET, value = "/user/")
    public ResponseEntity<List<User>> listAllUsers() {
        final List<User> users = userService.findAllUsers();
        if(users.isEmpty()) {
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        }
        return new ResponseEntity<List<User>>(users, HttpStatus.OK);
    }

    @RequestMapping(method = RequestMethod.GET, value = "/user/{id}")
    public ResponseEntity<?> getUser(@PathVariable("id") long id) {
        final User user = userService.findUserById(id);
        if(user == null) {
            return new ResponseEntity<>(new CustomErrorType(String.format("User with id %s not found", id)), HttpStatus.NOT_FOUND);
        }
        return new ResponseEntity<User>(user, HttpStatus.OK);
    }

    @RequestMapping(method = RequestMethod.POST, value = "/user/")
    public ResponseEntity<?> createUser(@RequestBody User user, UriComponentsBuilder ucBuilder) {
        if(userService.doesUserExist(user)) {
            return new ResponseEntity<>(new CustomErrorType(String.format("Unable to create, user %s already exists", user.getName())), HttpStatus.CONFLICT);
        }
        userService.createUser(user);

        final HttpHeaders headers = new HttpHeaders();
        headers.setLocation(ucBuilder.path("/api/user/{id}").buildAndExpand(user.getId()).toUri());
        return new ResponseEntity<String>(headers, HttpStatus.CREATED);
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/user/{id}")
    public ResponseEntity<?> updateUser(@PathVariable("id") long id,@RequestBody User user) {
        User currentUser = userService.findUserById(id);
        if(currentUser == null) {
            return new ResponseEntity<>(new CustomErrorType(String.format("Unable to create update, User with id %s not found", user.getId())), HttpStatus.NOT_FOUND);
        }
        currentUser.setName(user.getName());
        currentUser.setAge(user.getAge());
        currentUser.setSalary(user.getSalary());

        userService.updateUser(currentUser);
        return new ResponseEntity<User>(currentUser, HttpStatus.OK);
    }

    @RequestMapping(method = RequestMethod.DELETE, value = "/user/{id}")
    public ResponseEntity<?> deleteUser(@PathVariable("id") long id) {
        User user = userService.findUserById(id);

        if(user == null) {
            return new ResponseEntity<>(new CustomErrorType(String.format("Unable to delete user, user with id %s not found", id)), HttpStatus.NOT_FOUND);
        }
        userService.deleteUserById(id);
        return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
    }

    @RequestMapping(method = RequestMethod.DELETE, value = "/user/")
    public ResponseEntity<User> deleteAllUsers() {
        userService.deleteAllUsers();
        return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
    }
 }

我已经使用mockMvc对web层进行了测试,用户服务bean按照标准进行了模拟:

重启控制器监控测试。爪哇

package com.spring.ocr.rest.restconsume.controller;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.util.ArrayList;
import java.util.List;

import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.ocr.rest.restconsume.model.User;
import com.spring.ocr.rest.restconsume.service.UserService;

@RunWith(SpringRunner.class)
@WebMvcTest(RestApiController.class)
public class RestApiControllerUnitTest {

    @Autowired
    private MockMvc mockMvc;
    @MockBean
    UserService userService;
    @Autowired
    ObjectMapper objectMapper;

    private final List<User> dummyUserList = getDummyUserList();
    private final User dummyUser = new User((long)1, "Dave", (short)30, (double)30000);
    private final User dummyUpdatedUser = new User((long)1, "David", (short)31, (double)35000);

    @Test
    public void test_listAllUsers_userListSizeIs4_returnsListSizeOf4AndOkStatus() throws Exception {
        when(userService.findAllUsers()).thenReturn(dummyUserList);
        this.mockMvc.perform(get("/api/user/"))
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(jsonPath("$", hasSize(4)));
    }

    @Test
    public void test_listAllUsers_userListIsEmpty_returnsNoContentStatus() throws Exception {
        when(userService.findAllUsers()).thenReturn(new ArrayList<User>());
        this.mockMvc.perform(get("/api/user/"))
            .andDo(print())
            .andExpect(status().isNoContent());
    }

    @Test
    public void test_getUser_userExists_returnsUser() throws Exception {
        when(userService.findUserById(dummyUser.getId())).thenReturn(dummyUser);
        this.mockMvc.perform(get("/api/user/" + dummyUser.getId()))
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.id",is((int)dummyUser.getId())))
            .andExpect(jsonPath("$.name", is(dummyUser.getName())))
            .andExpect(jsonPath("$.age", is((int)dummyUser.getAge())))
            .andExpect(jsonPath("$.salary", is(dummyUser.getSalary())));
    }

    @Test
    public void test_getUser_userDoesntExist_returnsNotFoundStatusAndCustomErrorString() throws Exception {
        when(userService.findUserById(dummyUser.getId())).thenReturn(null);
        this.mockMvc.perform(get("/api/user/"+dummyUser.getId()))
            .andDo(print())
            .andExpect(status().isNotFound())
            .andExpect(content().string(containsString("User with id 1 not found")));
    }

    @Test
    public void test_createUser_userDoesNotExist_userCreated() throws Exception {
        final String dummyUserJson = objectMapper.writeValueAsString(dummyUser);
        when(userService.doesUserExist(dummyUser)).thenReturn(false);
        MvcResult result = this.mockMvc.perform(post("/api/user/")
            .contentType(MediaType.APPLICATION_JSON)
            .content(dummyUserJson))
            .andDo(print())
            .andExpect(status().isCreated())
            .andReturn();
        final String header = result.getResponse().getHeader("Location");
        assertThat(header, is("http://localhost/api/user/1"));
    }

    @Test
    public void test_createUser_userExists_returnsNotFoundStatusAndCustomErrorMessage() throws Exception {
        final String dummyUserJson = objectMapper.writeValueAsString(dummyUser);
        final String expectedContent = String.format("Unable to create, user %s already exists", dummyUser.getName());
        when(userService.doesUserExist(anyObject())).thenReturn(true);
        this.mockMvc.perform(post("/api/user/")
            .contentType(MediaType.APPLICATION_JSON)
            .content(dummyUserJson))
            .andDo(print())
            .andExpect(status().isConflict())
            .andExpect(jsonPath("$.errorMessage", is(expectedContent)));
    }

    @Test
    public void test_updateUser_userExists_returnsOkStatusAndUpdatedUser() throws Exception {
        final String dummyUpdatedUserJson = objectMapper.writeValueAsString(dummyUpdatedUser);
        when(userService.findUserById(dummyUser.getId())).thenReturn(dummyUser);
        doNothing().when(userService).updateUser(dummyUser);
        this.mockMvc.perform(put("api/user/" + dummyUser.getId())
            .contentType(MediaType.APPLICATION_JSON)
            .content(dummyUpdatedUserJson))
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.age", is(dummyUpdatedUser.getAge())))
            .andExpect(jsonPath("$.name", is(dummyUpdatedUser.getName())))
            .andExpect(jsonPath("$.salary", is(dummyUpdatedUser.getSalary())));
    }

    @Test
    public void test_deleteUser_userExists_returnNoContentStatus() throws Exception {
        when(userService.findUserById(dummyUser.getId())).thenReturn(dummyUser);
        this.mockMvc.perform(delete("api/user/" + dummyUser.getId()))
            .andDo(print())
            .andExpect(status().isNotFound());
    }

    @Test
    public void test_deleteUser_userDoesntExist_returnsNotFoundStatusAndCustomErrorMessage () throws Exception {
        when(userService.findUserById(dummyUser.getId())).thenReturn(null);
        final String expectedContent = String.format("Unable to create update, User with id %s not found", dummyUser.getName());
        this.mockMvc.perform(delete("api/user/"+dummyUser.getId()))
            .andDo(print())
            .andExpect(status().isNotFound())
            .andExpect(jsonPath("$.errorMessage", is(expectedContent)));
    }

    @Test
    public void test_deleteAllUsers_usersListPopulated_returnNoContentStatus() throws Exception {
        this.mockMvc.perform(delete("api/user/").contentType(MediaType.APPLICATION_JSON))
            .andDo(print())
            .andExpect(status().isNotFound());
    }

    private List<User> getDummyUserList() {
        final List<User> dummyUserList = new ArrayList<>();
        dummyUserList.add(new User((long)1, "Dave", (short)30, (double)30000));
        dummyUserList.add(new User((long)2, "Jess", (short)20, (double)20000));
        dummyUserList.add(new User((long)3, "Mike", (short)40, (double)40000));
        dummyUserList.add(new User((long)4, "Molly", (short)50, (double)50000));
        return dummyUserList;
    }
}

testtest\u updateUser\u userExists\u returnsOkStatusAndUpdatedUser正在返回404而不是200状态,并且test\u deleteUser\u userdoesntextist\u returnsnotfoundstatus和customerrormessage没有返回正文中的错误消息,这暗指404不是“真正的”404(它没有返回,因为正确的响应正在返回,它返回是因为其他原因)。我还认为其他404状态中的一些可能会在相同的上下文中返回。

共有1个答案

刘畅
2023-03-14

问题是由于失败测试中使用的控制器方法缺少“/”。

 类似资料:
  • 问题内容: 有没有人看到像这样的方法签名后放置的数组? 版画 过去,“ C”兼容性是一种奇怪的表示法,但我也无法想象有人用C编写这种代码。 有谁知道为什么甚至允许这样做? 如果有问题,我正在使用Java 7 update 10。 这与Java 6中的功能相同。http://ideone.com/91rZV1 顺便说一句,这不会编译,我也不希望它编译 问题答案: 有谁知道为什么甚至允许这样做? 在这

  • 我将数据保存到会话中,但是我尝试将其读回,结果为空。Spring MVC是我的后端,Angular 4是前端。 爪哇: 角: 你知道我错过了什么吗?也许是CORS的事?

  • 我编写了controller,它为每个映射使用了不同的值。现在我将它简化为对所有映射使用相同的值,但是我不知道如何使test工作,因为它在每个映射上都返回404。 这里是我的控制器: 和我的测试: 404及以下所有测试结果: 在org.springframework.test.util.assertionerrors.fail(assertionerrors.java:59)在org.spring

  • 但是,当从handleAsyncErrors()流链接ObjectNode并到达相同的httpCallbackFlow()时,我们会得到一个异常,该异常由 restClientException:无法写入请求:在org.springframework.web.client.restTemplate$HttpEntityRequestCallback.dowithRequest(restTempla

  • 问题内容: 尝试这段代码。为什么getValueB()返回1而不是2?毕竟,递增两次被调用两次。 问题答案: 毕竟,递增两次被调用两次。 是的,但是返回值是 在 第二次调用 之前 确定的。 返回的值由该 时间点在 return语句中的表达式求值确定,而不是“仅在执行离开方法之前”。 从JLS的14.17节开始: 一个带有Expression的return语句试图将控制权转移到包含它的方法的调用者;

  • 输入df。mean() 输出: 输入 (正确)输出: “a”中的类型值col=int 其他col具有str值 为什么会发生这种情况