2

在我的单元测试中,我们发现

this.mockMvc
  .perform(post("/authenticate")
    .contentType(MediaType.APPLICATION_FORM_URLENCODED)
    .param("username", "user@example.com")
    .param("password", "superSecretPassword"))
  .andExpect(status().isOk())
  .andDo(document("preprocessed-request",
    preprocessRequest(replacePattern(Pattern.compile("superSecretPassword"), "XXX"))));

参看。Spring REST 文档文档

build/generated-snippets/preprocessed-request/http-request.adoc与内容一起生成

[source,http]
----
POST /authenticate HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=user%40example.com&password=superSecretPassword
----

但我希望密码会因为 replacePattern() 而被屏蔽:

[source,http]
----
POST /authenticate HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=user%40example.com&password=XXX
----

我能做些什么?

4

1 回答 1

5

由于 MockMvc 如何处理请求参数的不幸副作用,模式替换没有效果。replacePattern作用于内容,即请求的主体,但 MockMvc 实际上并不在主体中包含表单编码的参数。

Spring REST Docs 在生成代码片段时足够聪明地处理这个问题,例如,对于表单 URL 编码的POST请求,它会查看参数以确定请求的主体应该是什么。应用时,它不会应用这些相同的智能replacePattern

您仍然可以使用自己OperationPreprocessor更改参数映射的密码来屏蔽密码。例如:

private OperationPreprocessor maskPassword() {
    return new PasswordMaskingPreprocessor();
}

private static class PasswordMaskingPreprocessor implements OperationPreprocessor {

    @Override
    public OperationRequest preprocess(OperationRequest request) {
        Parameters parameters = new Parameters();
        parameters.putAll(request.getParameters());
        parameters.set("password", "XXX");
        return new OperationRequestFactory().create(request.getUri(),
                request.getMethod(), request.getContent(), request.getHeaders(),
                parameters, request.getParts());
    }

    @Override
    public OperationResponse preprocess(OperationResponse response) {
        return response;
    }

}

然后,您可以使用这个新的预处理器代替replacePattern

this.mockMvc
  .perform(post("/authenticate")
    .contentType(MediaType.APPLICATION_FORM_URLENCODED)
    .param("username", "user@example.com")
    .param("password", "superSecretPassword"))
  .andExpect(status().isOk())
  .andDo(document("preprocessed-request",
    preprocessRequest(maskPassword())));
于 2015-10-22T14:28:29.297 回答