前言
在之前进行用户认证单元测试的时候,应用的是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<Town> townArgumentCaptor = ArgumentCaptor.forClass(Town.class); ArgumentCaptor<Long> 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掉的办法来进行单元测试,才明确原来单元测试应用始终不对!