近期学习总结

前言 在之前进行用户认证单元测试的时候,使用的是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掉的方法来进行单元测试,才明白原来单元测试使用一直不对!

    推荐阅读