zoukankan      html  css  js  c++  java
  • spring boot单元测试之十五:用mockmvc测试返回异步结果的controller(spring boot 2.4.4)

    一,演示项目相关信息

    1,地址:

    https://github.com/liuhongdi/asynctest

    2, 功能:演示用mockmvc测试返回异步结果的controller

    3,项目结构:如图:

    说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

             对应的源码可以访问这里获取: https://github.com/liuhongdi/

    说明:作者:刘宏缔 邮箱: 371125307@qq.com

    二,java代码

    1,controller/HomeController.java

    @RestController
    @RequestMapping("/home")
    public class HomeController {
    
        @Autowired
        private HelloService helloService;
    
        /**
         * 异步方法
         * @return
         */
        @RequestMapping("/callable")
        public Callable<String> deferredResult() throws Exception {
            System.out.println("控制层执行线程:" + Thread.currentThread().getName());
            return new Callable<String>() {
                @Override
                public String call() throws Exception {
                    System.out.println("异步执行线程:" + Thread.currentThread().getName());
                    String str = helloService.task2();
                    Thread.sleep(1000);
                    return str;
                }
            };
        }
    
        /**
         * 异步方法
         * @return
         */
        @RequestMapping("/async")
        public String getAsynHello(){//异步
            String s = helloService.asynchSayHello();
            System.out.println(s);
            return s;
        }
    
        /**
         * 同步方法
         * * @return
         */
        @GetMapping("/sync")
        public String getSyncHello(){//异步
            String s = helloService.synchSayHello();return s;
        }
    }

    2,service/HelloService.java

    @Service
    public class HelloService {
    
        @Resource
        private SleepService sleepService;
    
        //callable中调用的方法
        public String task2 () throws Exception {
            System.out.println("异步:线程名: " +Thread.currentThread().getName());
            Thread.sleep(2000);
            return "this is callable";
        }
    
       //同步方法
        public String synchSayHello() {
            try {
                //sleepService.syncSleep();
                System.out.println("同步:线程名: " +Thread.currentThread().getName());
                Thread.sleep(3000);
                return "this is sync";
            } catch (InterruptedException e) {
                e.printStackTrace();
                return "error";
            }
        }
    
        //调用异步的asyncsleep方法
        public String asynchSayHello() {
            try {
                System.out.println("异步:线程名1: " +Thread.currentThread().getName());
                sleepService.asyncSleep();
                return "this is async";
            } catch (Exception e) {
                e.printStackTrace();
                return "error";
            }
        }
    }

    3,service/SleepService.java

    @Service
    public class SleepService {
    
        //异步方法
        @Async
        public void asyncSleep() throws Exception{
            System.out.println("异步:线程名2: " +Thread.currentThread().getName());
            Thread.sleep(3000);
        }
    
    }

    4,controller/HomeControllerTest.java

    @AutoConfigureMockMvc
    @SpringBootTest
    class HomeControllerTest {
    
        @Autowired
        private MockMvc mockMvc;
    
        @Test
        @DisplayName("测试callable正确执行返回字符串")
        void callableResult() throws Exception {
            /*
            MvcResult result = mockMvc.perform(get("/home/callable")) //执行请求 
               .andExpect(request().asyncStarted())
                //.andExpect(request().asyncResult(CoreMatchers.instanceOf(User.class))) //默认会等10秒超时 
                .andReturn(); 
    
                mockMvc.perform(asyncDispatch(result)) 
                .andExpect(status().isOk()) 
                .andExpect(content().contentType(MediaType.APPLICATION_JSON)) 
                .andExpect(jsonPath("$.id").value(1));
            */
    
            MvcResult mvcResult = mockMvc.perform(get("/home/callable"))
                    .andExpect(request().asyncStarted())
                .andReturn();
    
            mockMvc.perform(asyncDispatch(mvcResult))
                .andExpect(status().isOk())
                .andExpect(content().string("this is callable"));
        }
    
    
        @Test
        @DisplayName("测试callable不正确执行返回字符串")
        void deferredResult() throws Exception {
            MvcResult mvcResult = mockMvc.perform(get("/home/callable")
                    .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                    .andReturn();
            String content = mvcResult.getResponse().getContentAsString();
            assertThat(content, equalTo(""));
        }
    
        @Test
        @DisplayName("测试async返回字符串")
        void getAsynHello() throws Exception {
            MvcResult mvcResult = mockMvc.perform(get("/home/async")
                    .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                    .andReturn();
            String content = mvcResult.getResponse().getContentAsString();
            assertThat(content, equalTo("this is async"));
        }
    
        @Test
        @DisplayName("测试sync返回字符串")
        void getSyncHello() throws Exception {
            MvcResult mvcResult = mockMvc.perform(get("/home/sync")
                    .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                    .andReturn();
            String content = mvcResult.getResponse().getContentAsString();
            assertThat(content, equalTo("this is sync"));
        }
    }

    三,测试效果

    四,备注

    1,controller在返回callable结果时,mockmvc的请求结果会为空

    2,@Async注解需要添加到另一个类中的方法上调用,

    不能调用本类中的async方法,
    否则会不生效 

    五,查看spring boot的版本:

      .   ____          _            __ _ _
     /\ / ___'_ __ _ _(_)_ __  __ _    
    ( ( )\___ | '_ | '_| | '_ / _` |    
     \/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::                (v2.4.4)
  • 相关阅读:
    haproxy配置ca证书
    gnu make
    工程引用libm.a文件的sin函数后
    bin utilities related
    ELF文件之九——使用链接脚本-2个函数-data-bss-temp-call-debug信息-struct
    ELF文件之八——使用链接脚本-2个函数-data-bss-temp-call-debug信息
    ELF文件之七——使用链接脚本-2个函数-data-bss-temp-call
    网站访问日志User Agent对照表
    jeecms上传文件限制导致413-Request Entity Too Large
    URL参数带加号“+”AJAX传值失败的解决方法
  • 原文地址:https://www.cnblogs.com/architectforest/p/14611088.html
Copyright © 2011-2022 走看看