Java知识点总结:想看的可以从这里进入

2.13、测试

测试就是在开发过程中用来检测某一段代码的功能是否能正确执行,Spring Boot 项⽬创建时会默认单元测试框架 spring-boot-test,它Spring Test、JUnit等其他测试框架结合起来(JUnit 5、AssertJ、Hamcrest、Mockito、JSONassert、JsonPath、Spring Test和Spring Boot Test)。

在使用测试是可以直接通过启动器:spring-boot-starter-test得到测试的支持。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>

在SpringBoot中提供了一些注解来帮助我们进行测试:

  1. @SpringBootTest:寻找一个主配置类(@SpringBootApplication),并使用它来启动Spring应用程序上下文。SpringBootTest加载完整的应用程序并注入所有可能的bean,因此需要一定时间。

    1. MOCK(默认值):加载web ApplicationContext并提供一个模拟web环境,嵌入式服务器不会启动,可以与@AutoConfigureMockMvc或@AutoConfigureWebTestClient一起使用,用于基于模拟的web应用程序测试。
    2. RANDOM_PORT:加载一个WebServerApplicationContext并提供一个真实的web环境。嵌入式服务器在一个随机端口上启动并监听。
    3. DEFINED_PORT:加载WebServerApplicationContext并提供一个真实的web环境。嵌入式服务器将启动并在一个已定义的端口(yml中)或默认端口8080上侦听。
    4. NONE:通过使用SpringApplication加载ApplicationContext,但不提供任何web环境(模拟或其他)。
  2. @Test:用在方法上进行测试实际的业务逻辑

  3. @AutoConfigureMockMvc:和SpringBootTest 一起使用,可以自动配置MockMvc,测试Controller

2.12.1、 Junit单元测试
1、测试

需要添加用于单元测试的启动器,该启动器会自动导入 junit 的相关依赖:

<!--单元测试-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
image-20230309110302564

使用测试 可以对项目中的方法进行测试,看它的执行是否能达到我们的预期效果,对相应的类创建对应的测试类,在方法上添加注解 @Test,就能使测试方法如同 main方法一样可以直接运行,这样就能观察到该方法最终执行的效果。

我们可以使用 IDEA 对某个类直接生成单元测试类。

  • 在相应的类中 按 ctrl+shitf+T快捷键

    image-20220924152420422 image-20220924152204998
  • 选择需要测试的方法,并生成测试的类(⽣成了单元测试的框架类,具体的业务代码要⾃⼰填充)

    image-20220924152552459
  • 选择一个select 方法生成测试类

    image-20220924153708481
  • 添加注解SpringBootTest注解(可以加载被管理的Bean),并编写业务逻辑

    image-20220924154713768
2、常用注解
  1. @SpringBootTest:是一个组合注解,内部含有 JUnit5中使用 的运行器注解 @ExtendWith

    image-20230309111010563
  2. @Test:用在方法上,表示该方法是一个测试用方法,使可以运行

  3. @DisplayName(“名称”):给测试类设置一个名称

  4. 增强处理

    1. @BeforeEach:前置方法,每个测试方法执行前都会执行
    2. @AfterEach:后置方法,在每个测试方法执行后都会执行
    3. @BeforeAll:表示在所有测试方法之前执行
    4. @AfterAll:表示在所有测试方法之后执行
    @SpringBootTest
    @Slf4j
    class JunitTest {
        @Test
        public void test() {
            log.info("测试1");
        }
        @Test
        public void test2() {
            log.info("测试2");
        }
        @Test
        public void test3(){
            log.info("测试3");
        }
    
        @BeforeEach
        public void BeforeEach(){
            log.info("在每个方法执行前执行");
        }
        @AfterEach
        public void afterEach(){
            log.info("在每个方法执行后执行");
        }
        @BeforeAll
        static void beforeAll(){
            log.info("在所有测试方法执行前执行");
        }
        @AfterAll
        static void afterAll(){
            log.info("在所有测试方法执行后执行");
        }
    }
    
    image-20230309112331581
  5. @Disabled:用在测试方法前,单独执行该方法时可以运行,但是如果点击测试类运行测试类内所有方法时,则加上此注解的方法不会运行

    image-20230309112559622

  6. @Timeout(value =超时时间,unit = 超时时间单位):设置方法的执行时间,如果超时会出现异常。

    TimeUnit.DAYS:代表二十四小时的时间单位

    TimeUnit.HOURS:代表六十分钟的时间单位

    TimeUnit.MINUTES:代表六十秒的时间单位。

    TimeUnit.SECONDS:时间单位代表一秒

    TimeUnit.MILLISECONDS:表示千分之一秒的时间单位。

    TimeUnit.MICROSECONDS:表示千分之一毫秒的时间单位

    TimeUnit.NANOSECONDS:表示千分之一微秒的时间单位

  7. @RepeatedTest(次数) :该方法每次运行都会执行指定次数。需要去掉@Test注解

    image-20230309113407342

    image-20230309113438627

3、断言

其中类Assertions是支持在测试中断言条件的实用方法的集合,除非另有说明,否则失败的断言将抛出org.opentest4j.AssertionFailedError或其子类。所有 JUnit断言 都是 org.junit.jupiter.Assertions 类中的静态方法

1、assertTrue(boolean condition):判断给定的boolean是否为true
2、assertFalse(boolean condition):判断给定的boolean是否为false
3、assertNull(Object actual):判断 Object 是否为null
4、assertNotNull(Object actual):判断 Object 不是null
5、assertEquals(o1,o2):判断两个对象是否相等
6、assertArrayEquals([][]):判断连个数组是否相等
2.12.2、MockMvc

Junit 无法测试Controller中的方法,因为它是一种网络请求,所有我们可以使用 MockMvc 对Controller方法 进行测试

MockMvc是由spring-test包提供,MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,使请求的验证变得更加方便。

这里有两个注解:

  • @WebMvcTest:使用此注解会禁用完全自动配置,仅仅配置MVC相关配置

    image-20220925100447808
  • @AutoConfigureMockMvc:自动配置MockMvc

使用@AutoConfigureMockMvc+@SpringBootTest进行测试:

  • 正常创建Controller

    @Controller
    @RequestMapping("/testMockMvc")
    public class UserinfoController {
        @Resource
        private UserinfoService userinfoService;
    
        @GetMapping("/getUserinfo")
        @ResponseBody
        public Userinfo userinfo(long id){
            return userinfoService.getById(id);
        }
    
        @GetMapping("/hello")
        public String hello(String name , Model model){
            model.addAttribute("user", name+"欢迎欢迎");
            return "hello";
        }
    }
    
  • 编写测试类

    @SpringBootTest
    @AutoConfigureMockMvc
    public class UserControllerTest {
       
        @Autowired
        private MockMvc mockMvc;
        /*
         * 1、mockMvc.perform执行一个请求。
         * 			MockMvcRequestBuilders.get("XXX") get提交访问controller的一个接口。
         *    		MockMvcRequestBuilders.post("XXX") post提交访问controller的一个接口。
         * 			.param  传递的参数
         * 			.accept(MediaType.TEXT_HTML_VALUE))接受的响应结果的文档类型
         *    		.contentType   请求数据的文档类型
         *			.content()   可以传递JSON数据
         * 2、.andExpect  添加执行完成后的断言。
         * 3、.andDo  添加一个结果处理器,表示要对结果做点什么事情
         *   比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息。
         * 7、.andReturn表示执行完成后返回相应的结果。
         */
        @Test
        public void getUserinfo() throws Exception {
            MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/testMockMvc/getUserinfo")
                            .param("id","1")
                            .contentType(MediaType.APPLICATION_JSON)
                    ).andDo(print())
                    .andExpect(status().isOk())
                    .andReturn();
    
        }
        @Test
        public void hello() throws Exception {
            MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/testMockMvc/hello")
                            .param("name","yu")
                    ).andDo(print())
                    .andExpect(status().isOk())
                    .andReturn();
    
        }
    }
    
  • 测试页面跳转

    image-20230309143545367
  • 测试返回数据

    image-20230309143749907

更多推荐