package com.lovecoding.springboot.demo.demo;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;


/**
 * 单元测试 指的时 我们开发过程当中对我们自己的 功能点进行测试
 * 集成测试 指的的 把相关功能点串联 测试
 */


/**
 * 测试分为两类
 * 第一类是 框架全量加载 速度较慢， 但是走的是全流程
 * @SpringBootTest
 * @AutoConfigureMockMvc
 * 第二类是 测试指定类
 * @WebMvcTest(DemoController.class)
 */


//@SpringBootTest
//@AutoConfigureMockMvc
//@WebMvcTest(DemoController.class)
@WebFluxTest(DemoController.class)
class DemoControllerTest {

    /**
     * 自动注入 MockMvc 对象。需要配合 @AutoConfigureMockMvc 注解一起使用
     */
    //@Resource
    //MockMvc mockMvc;

    /**
     * WebTestClient 测试工具 和 Mock 测试功能相近
     * 属于异步调用
     */
    @Resource
    WebTestClient webClient;

    /**
     * 创建MockBean 用于模拟 testMapper 返回值
     */
    @MockBean
    TestMapper testMapper;



    @Test
    public void webTest(){
        // WebTestClient 测试用例 的 请求构造
        webClient.get().uri("/")
                .accept(MediaType.APPLICATION_JSON_UTF8)
                .exchange().expectStatus().isOk();

    }

    @Test
    public void t(  @Autowired MockMvc mockMvc  ) throws Exception {

        /**
         * 创建虚拟返回值
         * 主要用于  还没有开发完成的工具类
         * 可以先定义返回值
         */
        when( testMapper.counter() ).thenReturn( 99999L );

        //发起一个请求  参数是  请求方法和 请求路径
        MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.request(
                                HttpMethod.GET, "/"
                        //设置请求 类型
                        ).contentType(MediaType.APPLICATION_JSON_VALUE)
                ).andDo(MockMvcResultHandlers.print())
                //创建 断言 判断请求返回值 是否是 200  如果不通过则 测试失败
                .andExpect(MockMvcResultMatchers.status().is(200))
                //创建 断言  判断页面返回内容 不是 99999 则 单元测试不通过
                .andExpect(MockMvcResultMatchers.content().string("99999"))
                // 解析 JSON 值  判断内容
                //.andExpect( MockMvcResultMatchers.jsonPath("$.data.code").value(200) )
                //返回 请求体
                .andReturn();

        System.out.println( mvcResult.getResponse().getContentAsString() );

    }

}