近期学习总结

前言

在之前进行用户认证单元测试的时候,使用的是RestTemplate来模拟发起请求,但是平时用的更多的是MockMvc来进行后台的请求。他们两个有何不同呢?

RestTemplate

部署的一个真实的web服务器来监听http请求,响应结果
既然是真实的,那么它最大的弊端就是无法进行事物回滚:
近期学习总结_第1张图片
在测试结束后,发现并没有对数据进行回滚,但是我在认证单元测试的时候并没有涉及到数据库回滚的问题,所以跟mockmvc没有区别
原因:@Transactional注解对于RestTemplate是失效的,所以不会进行事物回滚

MockMvc

mockmvc通常是通过设置一个完整的上下完应用程序来模拟HTTP请求和响应
创建的是一个假的DispatcherServlet来模拟MVC堆栈的运行,并没有真正的网络链接
近期学习总结_第2张图片
既然是模拟的,那么我们可以通过注解@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());
  }

image.png
首先是错误翻译:返回值的id属性不存在

排查:

1.第一反应以为是我C层Long属性写成Integer类型了
image.png

2.查看响应状态:passed,请求成功
近期学习总结_第3张图片

3.猜测返回值出了问题,因为请求是没有问题的:
image.png
仔细想了之后: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());
  }

image.png

与历史项目对比,找区别:
image.png
将至改为Long便可以成功访问了!

以为是自己的请求的为Long类型,但是想到转换了String类型了啊,跟Integer一样啊
近期学习总结_第4张图片
改为Integer测试还是不行!

总结

单元测试使用还是不够熟练,使用方法也不对,总是在都写完之后进行集成测试,在今天老师讲了可以将未实现的方法直接mock掉的方法来进行单元测试,才明白原来单元测试使用一直不对!

你可能感兴趣的:(近期学习总结)