近期学习总结
前言
在之前进行用户认证单元测试的时候,使用的是RestTemplate来模拟发起请求,但是平时用的更多的是MockMvc来进行后台的请求。他们两个有何不同呢?
RestTemplate
部署的一个真实的web服务器来监听http请求,响应结果
既然是真实的,那么它最大的弊端就是无法进行事物回滚:
文章图片
在测试结束后,发现并没有对数据进行回滚,但是我在认证单元测试的时候并没有涉及到数据库回滚的问题,所以跟mockmvc没有区别
原因:@Transactional注解对于RestTemplate是失效的,所以不会进行事物回滚
MockMvc
mockmvc通常是通过设置一个完整的上下完应用程序来模拟HTTP请求和响应
创建的是一个假的DispatcherServlet来模拟MVC堆栈的运行,并没有真正的网络链接
文章图片
既然是模拟的,那么我们可以通过注解@Transactional来进行事务的回滚,并不会因为测试对数据库造成副作用。
总结
综上:在更多时候进行单元测试的时候我们还是应该倾向于MockMvc的,但是当有特殊需求的时候,我们可以使用RestTemplate。
单元测试遇到的问题:
问题一:
仿照之前老项目写update的单元测试代码:
@Test
void update() throws Exception {
Long id = new Random().nextLong();
Town oldTown = getOneTown();
oldTown.setId(id);
Town newTown = getOneTown();
String jsonString = JSON.toJSONString(oldTown);
String url = baseUrl + "/" + id.toString();
Mockito.doReturn(newTown).when(this.townService).update(id, oldTown);
MockHttpServletRequestBuilder putRequest = MockMvcRequestBuilders
.put(url)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonString);
this.mockMvc.perform(putRequest)
.andExpect(MockMvcResultMatchers.jsonPath("$.id").value(newTown.getId()))
.andExpect(MockMvcResultMatchers.jsonPath("$.name").exists())
.andExpect(MockMvcResultMatchers.jsonPath("$.pinyin").exists())
.andExpect(status().isOk());
ArgumentCaptor townArgumentCaptor = ArgumentCaptor.forClass(Town.class);
ArgumentCaptor longArgumentCaptor = ArgumentCaptor.forClass(Long.class);
Mockito.verify(this.townService).update(longArgumentCaptor.capture(),
townArgumentCaptor.capture());
org.assertj.core.api.Assertions.assertThat(longArgumentCaptor.getValue()).isEqualTo(id);
org.assertj.core.api.Assertions.assertThat(townArgumentCaptor.getValue().getName()).isEqualTo(oldTown.getName());
}
文章图片
首先是错误翻译:返回值的id属性不存在
排查:
1.第一反应以为是我C层Long属性写成Integer类型了
文章图片
2.查看响应状态:passed,请求成功
文章图片
3.猜测返回值出了问题,因为请求是没有问题的:
文章图片
仔细想了之后:oldTown在模拟发起请求的时候,传入的oldTown与mock中的oldTown就不是一个对象了,那他必然不会返回newTown!
总结
还是对于单元测试缺少锻炼,还需要通过不断的写来加深理解。
问题二:
根据id获取对象c层测试:
@Test
void getById() throws Exception{
Town town = getOneTown();
Mockito.doReturn(town).when(this.townService).getById(Mockito.eq(town.getId()));
String url = baseUrl + "/" + town.getId().toString();
this.mockMvc.perform(MockMvcRequestBuilders.get(url))
.andExpect(MockMvcResultMatchers.status().isOk());
}
文章图片
与历史项目对比,找区别:
文章图片
将至改为Long便可以成功访问了!
【近期学习总结】以为是自己的请求的为Long类型,但是想到转换了String类型了啊,跟Integer一样啊
文章图片
改为Integer测试还是不行!
总结 单元测试使用还是不够熟练,使用方法也不对,总是在都写完之后进行集成测试,在今天老师讲了可以将未实现的方法直接mock掉的方法来进行单元测试,才明白原来单元测试使用一直不对!
推荐阅读
- 由浅入深理解AOP
- 7.9号工作总结~司硕
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- 一起来学习C语言的字符串转换函数
- 定制一套英文学习方案
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- 《深度倾听》第5天──「RIA学习力」便签输出第16期
- 如何更好的去学习
- 【韩语学习】(韩语随堂笔记整理)