zoukankan      html  css  js  c++  java
  • SpringCloud单元测试【六】

    SpringCloud的单元测试主要是依靠 Mock以及Mockito, 所以我们需要对Mock以及Mockito有一定的认识。

    一、为什么要用MockMvc

      可能我们在测试控制层的代码都是启动服务器,在浏览器中输入URL,然后开始测试是否达到预期效果,发生错误的话,修改相关代码并重启服务器再次进行测试。分析一下这个过程,启动服务器-->打开浏览器-->输入URL-->等待返回结果-->修复bug-->重启服务器.....循环。
      其中的缺点也挺明显的,在浏览器输入URL的地址,如果是GET请求还好,POST请求或者DELETE请求怎么办?只能借助其他工具,通过命令行编写curl语句,或者借助谷歌浏览器的postman插件,亦或者自己在代码中通过编写相应httpClient方法来实现测试,但是这几种方法都较为麻烦,而且测试用例并不能较好的保存。再说一个缺点,代码修改后,往往需要再次重启服务器,等待启动完毕才能接下来的测试过程。
      如果tomcat服务器启动速度较慢,这将是一件非常痛苦的事情,测试验证也不方便,且依赖网络环境,这些原因导致测试起来很麻烦,而为了可以方便对Controller进行测试,且很好的保存和循环使用测试用例,则可以通过单元测试来解决,通过前面一篇文章,大家对于单元测试的便利性有了认识和体会,接下来通过引入MockMVC进行控制层的单元测试。

      MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。

    二、示例演示

    1. pom.xml中引入依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    2. 编写测试类

    在测试类前加上注解

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = EurekaClientApplication.class) //EurekaClientApplication是模块的启动类名
    @WebAppConfiguration
    @ContextConfiguration

    再加上

    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    再加上一个before

    @Before
    public void setUp() throws Exception {
            mvc = MockMvcBuilders
                    .webAppContextSetup(context)
                    .build();
    }

    在真实需要测试的代码中加入

    @Test
    public void contextLoads() throws Exception {
        MvcResult 
    //groupManager访问路径
    //param传入参数
    result=mvc.perform(MockMvcRequestBuilders.post("/groupManager").param("pageNum","1").param("pageSize","10")).andReturn();
        MockHttpServletResponse response = result.getResponse();
        String content = response.getContentAsString();
        List<JtInfoDto> jtInfoDtoList = GsonUtils.toObjects(content, new TypeToken<List<JtInfoDto>>() {}.getType());
        for(JtInfoDto infoDto : jtInfoDtoList){
            System.out.println(infoDto.getJtCode());
        }
    }

    3. 数据库回滚

    在测试类上添加注解@Rollback,同时测试方法加上注解@Transactional。

    如果不希望回滚 将rollback改为false即可

    4. 完整的测试代码

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = EurekaClientApplication.class)
    @WebAppConfiguration
    @ContextConfiguration
    public class EurekaClientApplicationTests {
    
        @Autowired
        private WebApplicationContext context;
    
        private MockMvc mvc;
    
        @Before
        public void setUp() throws Exception {
            mvc = MockMvcBuilders
                    .webAppContextSetup(context)
                    .build();
        }
    
        @Test
        public void contextLoads() throws Exception {
            MvcResult result=mvc.perform(MockMvcRequestBuilders.post("/groupManager").param("pageNum","1").param("pageSize","10")).andReturn();
            MockHttpServletResponse response = result.getResponse();
            String content = response.getContentAsString();
            List<JtInfoDto> jtInfoDtoList = GsonUtils.toObjects(content, new TypeToken<List<JtInfoDto>>() {}.getType());
            for(JtInfoDto infoDto : jtInfoDtoList){
                System.out.println(infoDto.getJtCode());
            }
        }
    
    }

    注意:我们大多数的时候是往控制层controller传递的不是一个简单的参数,可能是一个Map或一个实体类,发现怎么都传不过去,解决方法如下:

    在发送请求的时候,我们使用json的参数格式 

         Map params = new HashMap();
            params.put("name", "西瓜");
            params.put("unit","斤");
            params.put("price", "12.88");
            String requestJson = JSONObject.toJSONString(params);
            MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/good/save")
                    .contentType(MediaType.APPLICATION_JSON).content(requestJson))
                    .andDo(MockMvcResultHandlers.print())
                    .andExpect(MockMvcResultMatchers.status().is(200))
                    .andReturn();
            result.getResponse().setCharacterEncoding("UTF-8");
            System.out.println(result.getResponse().getContentAsString());

    然后controller的参数添加@RequestBody注解。

  • 相关阅读:
    RDIFramework.NET框架基于Quartz.Net实现任务调度详解及效果展示
    Quartz.Net实现作业定时调度详解
    微信公众号开发系列-13、基于RDIFramework.NET框架整合微信开发应用效果展示
    微信公众号开发C#系列-12、微信前端开发利器:WeUI
    微信公众号开发C#系列-11、生成带参数二维码应用场景
    微信公众号开发C#系列-10、长链接转短链接
    微信公众号开发C#系列-9、多公众号集中管理
    微信公众号开发C#系列-8、自定义菜单及菜单响应事件的处理
    微信公众号开发C#系列-7、消息管理-接收事件推送
    微信公众号开发C#系列-5、用户和用户组管理-支持同步
  • 原文地址:https://www.cnblogs.com/myitnews/p/11796321.html
Copyright © 2011-2022 走看看