概述
最近在做一个自动测试的平台,使用的是Spring的自带测试库。如何使用,这里不再说了,网上有很多,推荐开涛写的博客
我的主要测试代码:
//主要构造mock请求类,可以不用看
try {
for(TestClass tmpClass:classes){
List<TestUrl> urls = tmpClass.getUrls();
for(TestUrl url:urls){
String urlString = url.getCompositeUrl();
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get(urlString);
initRequestParams(requestBuilder,url);
mockMvc.perform(requestBuilder).andDo(MockMvcResultHandlers.print());
}
}
} catch (Exception e) {
e.printStackTrace();
}
//初始化request参数
private void initRequestParams(MockHttpServletRequestBuilder builder,TestUrl url) {
//设置编码格式
builder.characterEncoding("utf-8");
TestParameter parameter = url.getParamter();
TestContent content = url.getContent();
TestSession sessionData = url.getSession();
//添加session
if(sessionData != null){
MockHttpSession mockHttpSession = new MockHttpSession();
Map<String, Object> maps = sessionData.getSession();
Set<Map.Entry<String, Object>> sets = maps.entrySet();
for(Map.Entry<String, Object> entry:sets){
mockHttpSession.setAttribute(entry.getKey(), entry.getValue());
}
builder.session(mockHttpSession);
}
if(parameter != null){
Map<String, String> paramMaps = parameter.getParams();
Set<Map.Entry<String, String>> sets = paramMaps.entrySet();
StringBuilder paramBuilder = new StringBuilder();
for(Map.Entry<String, String> entry:sets){
paramBuilder.append('&');
paramBuilder.append(entry.getKey());
paramBuilder.append('=');
paramBuilder.append(entry.getValue());
}
String bodyData = paramBuilder.deleteCharAt(0).toString();
System.out.println(bodyData);
builder.content(bodyData);//这里是重点
builder.contentType(MediaType.APPLICATION_FORM_URLENCODED);//这里是重点
// for(Map.Entry<String, String> entry:sets){
// builder.param(entry.getKey(), entry.getValue());
// }
return;
}
}
根据HTTP协议,当body中参数以form表单格式进行提交时,在服务器端通过request.getParameter(“name”)来获取是可以获取到的,效果和在Url中使用参数是一样的。然而当我在这里设置参数时发现是有问题的,test结果显示缺少参数,而缺少的参数是在body里面的,这说明mock并没有content-type类型去解析content的数据。
于是我查看了Spring中MockHttpServletRequestBuilder的源码
...
private String contentType;//content类型
private byte[] content;//content数据
private final MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();//参数列表
....
/**
* Set the request body as a UTF-8 String.
* @param content the body content
*/
public MockHttpServletRequestBuilder content(String content) {
try {
this.content = content.getBytes("UTF-8");
}
catch (UnsupportedEncodingException e) {
// should never happen
}
return this;
}
/**
* Add a request parameter to the {@link MockHttpServletRequest}.
* <p>If called more than once, new values get added to existing ones.
* @param name the parameter name
* @param values one or more values
*/
public MockHttpServletRequestBuilder param(String name, String... values) {
addToMultiValueMap(this.parameters, name, values);//将name和value添加到parameter中,允许一个名字对应多个value值
return this;
}
Ok,以上是初始化的方法。下面是重点,builder的最终目的是build一个MockHttpServletRequest,而这个工作是有buildRequest()方法来完成的。
部分:
try {
if (this.url.getRawQuery() != null) {
request.setQueryString(this.url.getRawQuery());
}
MultiValueMap<String, String> queryParams =
UriComponentsBuilder.fromUri(this.url).build().getQueryParams();
for (Entry<String, List<String>> entry : queryParams.entrySet()) {
for (String value : entry.getValue()) {
value = (value != null) ? UriUtils.decode(value, "UTF-8") : null;
request.addParameter(UriUtils.decode(entry.getKey(), "UTF-8"), value);
}
}
}
catch (UnsupportedEncodingException ex) {
// shouldn't happen
}
for (String name : this.parameters.keySet()) {
for (String value : this.parameters.get(name)) {
request.addParameter(name, value);
}
}
request.setContentType(this.contentType);
request.setContent(this.content);
request.setCharacterEncoding(this.characterEncoding);
由buildRequest的代码可以发现,Mock将URL的参数和通过使用param添加的参数添加到request中的parameter中了,而将content内容、类型并没有进行解析,直接添加到request的content中了。
让我们再查看MockHttpServletRequest的代码:
@Override
public String getParameter(String name) {
String[] arr = (name != null ? this.parameters.get(name) : null);
return (arr != null && arr.length > 0 ? arr[0] : null);
}
MockHttpServletRequest实现了HttpServletRequest,而在getParameter进行了重写,即从parameter的map中进行读取。
这也就解释了文章开头提出的问题。
最后
以上就是热情猫咪为你收集整理的分析MockHttpServletRequestBuilder中content和param的区别的全部内容,希望文章能够帮你解决分析MockHttpServletRequestBuilder中content和param的区别所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复