我有简单的积分测试

@Test
public void shouldReturnErrorMessageToAdminWhenCreatingUserWithUsedUserName() throws Exception {
    mockMvc.perform(post("/api/users").header("Authorization", base64ForTestUser).contentType(MediaType.APPLICATION_JSON)
        .content("{\"userName\":\"testUserDetails\",\"firstName\":\"xxx\",\"lastName\":\"xxx\",\"password\":\"xxx\"}"))
        .andDo(print())
        .andExpect(status().isBadRequest())
        .andExpect(?);
}

在最后一行中,我想比较在响应体中接收到的字符串与预期的字符串

我得到的回答是:

MockHttpServletResponse:
          Status = 400
   Error message = null
         Headers = {Content-Type=[application/json]}
    Content type = application/json
            Body = "Username already taken"
   Forwarded URL = null
  Redirected URL = null

尝试了content(), body()的一些技巧,但都不起作用。


当前回答

这是一种更适合生产的方式,如果你可能有大的json响应,那么你不必用json字符串来混乱你的测试文件,只需从静态资源文件夹加载它们并直接断言它们。

  @Test
  @DisplayName("invalid fields")
  void invalidfields() throws Exception {

    String request = getResourceFileAsString("test-data/http-request/invalid-fields.json");
    String response_file_path = "test-data/http-response/error-messages/invalid-fields.json";
    String expected_response = getResourceFileAsString(response_file_path);

    mockMvc.perform(evaluateRulesOnData(TRACKING_ID.toString(), request))
        .andExpect(status().isBadRequest())
        .andExpect(content().json(expected_response));
  }

从类路径加载测试文件的助手函数

  public static String getResourceFileAsString(String fileName) throws IOException {
    Resource resource = new ClassPathResource(fileName);
    File file = resource.getFile();
    return new String(Files.readAllBytes(file.toPath()));
  }

预期的响应有一个包含列表中许多元素的数组,这些元素在每次测试运行期间都是随机顺序匹配的。

其他回答

String body = mockMvc.perform(bla... bla).andReturn().getResolvedException().getMessage()

这将为您提供响应的主体。“用户名已被占用”在你的情况下。

下面是一个例子,如何解析JSON响应,甚至如何以JSON形式发送一个bean请求:

  @Autowired
  protected MockMvc mvc;

  private static final ObjectMapper MAPPER = new ObjectMapper()
    .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    .registerModule(new JavaTimeModule());

  public static String requestBody(Object request) {
    try {
      return MAPPER.writeValueAsString(request);
    } catch (JsonProcessingException e) {
      throw new RuntimeException(e);
    }
  }

  public static <T> T parseResponse(MvcResult result, Class<T> responseClass) {
    try {
      String contentAsString = result.getResponse().getContentAsString();
      return MAPPER.readValue(contentAsString, responseClass);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  @Test
  public void testUpdate() {
    Book book = new Book();
    book.setTitle("1984");
    book.setAuthor("Orwell");
    MvcResult requestResult = mvc.perform(post("http://example.com/book/")
      .contentType(MediaType.APPLICATION_JSON)
      .content(requestBody(book)))
      .andExpect(status().isOk())
      .andReturn();
    UpdateBookResponse updateBookResponse = parseResponse(requestResult, UpdateBookResponse.class);
    assertEquals("1984", updateBookResponse.getTitle());
    assertEquals("Orwell", updateBookResponse.getAuthor());
  }

正如您在这里看到的,Book是一个请求DTO, UpdateBookResponse是一个从JSON解析的响应对象。您可能想要更改Jackson的ObjectMapper配置。

一种可能的方法是简单地包含gson依赖:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
</dependency>

并解析该值来进行验证:

@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class HelloControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private HelloService helloService;

    @Before
    public void before() {
        Mockito.when(helloService.message()).thenReturn("hello world!");
    }

    @Test
    public void testMessage() throws Exception {
        MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/"))
                .andExpect(status().isOk())
                .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON_VALUE))
                .andReturn();

        String responseBody = mvcResult.getResponse().getContentAsString();
        ResponseDto responseDto
                = new Gson().fromJson(responseBody, ResponseDto.class);
        Assertions.assertThat(responseDto.message).isEqualTo("hello world!");
    }
}

另一个例子是:

.andExpect (jsonPath(“$”)。value(containsString("你已成功删除")));

身体反应:

Body =成功删除ID为1的[Object]

Spring security的@WithMockUser和hamcrest的containsString匹配器提供了一个简单而优雅的解决方案:

@Test
@WithMockUser(roles = "USER")
public void loginWithRoleUserThenExpectUserSpecificContent() throws Exception {
    mockMvc.perform(get("/index"))
            .andExpect(status().isOk())
            .andExpect(content().string(containsString("This content is only shown to users.")));
}

更多的例子在github上