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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM