Spring Boot

您所在的位置:网站首页 junit报告 Spring Boot

Spring Boot

2024-07-10 04:17| 来源: 网络整理| 查看: 265

Pre

SpringBoot - 单元测试利器Mockito入门

SpringBoot - 应用程序测试方案

SpringBoot - @SpringBootTest加速单元测试的小窍门

Spring Boot - Junit4 / Junit5 / Spring Boot / IDEA 关系梳理

​代码语言:javascript复制package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.platform.commons.annotation.Testable; /** * {@code @Test} is used to signal that the annotated method is a * test method. * *

{@code @Test} methods must not be {@code private} or {@code static} * and must not return a value. * *

{@code @Test} methods may optionally declare parameters to be * resolved by {@link org.junit.jupiter.api.extension.ParameterResolver * ParameterResolvers}. * *

{@code @Test} may also be used as a meta-annotation in order to create * a custom composed annotation that inherits the semantics of * {@code @Test}. * * Test Execution Order * *

By default, test methods will be ordered using an algorithm that is * deterministic but intentionally nonobvious. This ensures that subsequent runs * of a test suite execute test methods in the same order, thereby allowing for * repeatable builds. In this context, a test method is any instance * method that is directly annotated or meta-annotated with {@code @Test}, * {@code @RepeatedTest}, {@code @ParameterizedTest}, {@code @TestFactory}, or * {@code @TestTemplate}. * *

Although true unit tests typically should not rely on the order * in which they are executed, there are times when it is necessary to enforce * a specific test method execution order — for example, when writing * integration tests or functional tests where the sequence of * the tests is important, especially in conjunction with * {@link TestInstance @TestInstance(Lifecycle.PER_CLASS)}. * *

To control the order in which test methods are executed, annotate your * test class or test interface with {@link TestMethodOrder @TestMethodOrder} * and specify the desired {@link MethodOrderer} implementation. * * @since 5.0 * @see RepeatedTest * @see org.junit.jupiter.params.ParameterizedTest * @see TestTemplate * @see TestFactory * @see TestInfo * @see DisplayName * @see Tag * @see BeforeAll * @see AfterAll * @see BeforeEach * @see AfterEach */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") @Testable public @interface Test { }JUnit 4 vs JUnit 5

以下是JUnit 4和JUnit 5注解之间的一些主要区别

功能/特性

JUnit 4注解

JUnit 5注解

测试方法声明

@Test

@Test

测试类声明

@RunWith

@ExtendWith

断言

org.junit.Assert类

org.junit.jupiter.api.Assertions类

测试生命周期

@BeforeAll, @BeforeEach, @AfterEach, @AfterAll

参数化测试

@Parameterized

@ParameterizedTest

条件测试

@EnabledOnOs, @DisabledOnOs, @EnabledOnJre, @DisabledOnJre, 等等

标记重复测试

@RepeatedTest

依赖性测试

@Test中使用@TestDependsOn和@TestDependency

测试实例生命周期

@TestInstance

测试接口和默认方法

不支持

支持

扩展模型

自定义Runner

自定义Extension

这些是JUnit 4和JUnit 5之间的一些重要区别,JUnit 5引入了许多新的功能和改进,以提供更灵活、强大的测试框架。你可以根据项目的需要选择适合的JUnit版本。

Junit5 常用注解@SpringBootTest: 用于指定测试类启用Spring Boot Test,默认会提供Mock环境。@ExtendWith: 如果只想启用Spring环境进行简单测试,不想启用Spring Boot环境,可以配置扩展为:SpringExtension。@Test: 指定方法为测试方法。@TestMethodOrder: 用于配置测试类中方法的执行顺序策略,配置为OrderAnnotation时,按@Order顺序执行。@Order: 用于配置方法的执行顺序,数字越低执行顺序越高。@DisplayName: 用于指定测试类和测试方法的别名。@BeforeAll: 在测试类的所有测试方法前执行一次,可用于全局初始化。@AfterAll: 在测试类的所有测试方法后执行一次,可用于全局销毁资源。@BeforeEach: 在测试类的每个测试方法前都执行一次。@AfterEach: 在测试类的每个测试方法后都执行一次。@Disabled: 禁用测试方法。@RepeatedTest: 指定测试方法重复执行。@ParameterizedTest: 指定参数化测试方法,类似重复执行,从@ValueSource中获取参数。@ValueSource: 用于参数化测试指定参数。@AutoConfigureMockMvc: 启用MockMvc的自动配置,可用于测试接口。栗子

以下是上述注解的使用方法示例以及相应的Java代码:

@SpringBootTest:用于指定Spring Boot测试。示例:代码语言:javascript复制@SpringBootTest public class MySpringBootTest { // 测试方法 }@ExtendWith:用于配置测试类的执行环境。示例:代码语言:javascript复制@ExtendWith(SpringExtension.class) public class MySpringTest { // 测试方法 }@Test:指定方法为测试方法。示例:代码语言:javascript复制@Test public void testSomeMethod() { // 测试逻辑 }@TestMethodOrder 和 @Order:配置测试方法的执行顺序。示例:代码语言:javascript复制@TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class OrderedTestExample { @Order(1) @Test public void testMethod1() { // 测试逻辑 } @Order(2) @Test public void testMethod2() { // 测试逻辑 } }@DisplayName:用于指定测试类和测试方法的别名。示例:代码语言:javascript复制@DisplayName("My Test Suite") public class MyTestSuite { @Test @DisplayName("My Test Case") public void myTestCase() { // 测试逻辑 } }@BeforeAll 和 @AfterAll:在测试类的所有测试方法前和后执行一次,可用于全局初始化和销毁资源。示例:代码语言:javascript复制@BeforeAll public static void setup() { // 初始化操作 } @AfterAll public static void teardown() { // 资源销毁操作 }@BeforeEach 和 @AfterEach:在测试类的每个测试方法前和后都执行一次。示例:代码语言:javascript复制@BeforeEach public void beforeEachTest() { // 执行前的准备工作 } @AfterEach public void afterEachTest() { // 执行后的清理工作 }@Disabled:禁用测试方法。示例:代码语言:javascript复制@Test @Disabled("This test is not ready yet.") public void disabledTest() { // 未完成的测试逻辑 }@RepeatedTest:指定测试方法重复执行。示例:代码语言:javascript复制@RepeatedTest(5) public void repeatedTest() { // 该测试方法会重复执行5次 }@ParameterizedTest 和 @ValueSource:用于参数化测试。示例:代码语言:javascript复制@ParameterizedTest @ValueSource(strings = { "apple", "banana", "cherry" }) public void testFruit(String fruit) { // 使用参数化的水果名称进行测试 }@AutoConfigureMockMvc:启用MockMvc的自动配置,可用于测试接口。示例:代码语言:javascript复制@SpringBootTest @AutoConfigureMockMvc public class MyControllerIntegrationTest { @Autowired private MockMvc mockMvc; @Test public void testController() throws Exception { mockMvc.perform(get("/api/someendpoint")) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)); } }

这些示例演示了如何使用这些注解来编写JUnit 5和Spring Boot测试。您可以根据您的具体需求和测试场景进行相应的配置和使用。

代码语言:javascript复制package com.artisan.boottest.example; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class BasicTest { @Test public void test() { String artisan = "artisan good"; Assertions.assertEquals("artisan good", artisan); } }代码语言:javascript复制package com.artisan.boottest.example; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.junit.jupiter.SpringExtension; /** * @author 小工匠 * @version 1.0 * @description: JUnit指定方法测试顺序 * @mark: show me the code , change the world */ @Slf4j @ExtendWith(SpringExtension.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class MethodOrderTest { @Test @Order(1) @DisplayName("order为1的方法") void lowOrder(){ log.info("lowOrder method"); } @Test @Order(2) @DisplayName("order为2的方法") void highOrder(){ log.info("highOrder method"); } }代码语言:javascript复制package com.artisan.boottest.example; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.junit.jupiter.SpringExtension; /** * @author 小工匠 * @version 1.0 * @description: JUnit生命周期测试 * @mark: show me the code , change the world */ @Slf4j @ExtendWith(SpringExtension.class) public class LifecycleTest { @BeforeAll static void allInit() { log.info("allInit():在所有方法前执行,只执行一次"); } @BeforeEach void eachInit() { log.info("eachInit():在测试方法前执行,每个测试方法前都执行"); } @Test void successTest() { log.info("successTest():方法执行成功"); } @AfterEach void eachDown() { log.info("eachDown():在测试方法后执行,每个测试方法后都执行"); } @AfterAll static void allDown() { log.info("allDown():在测试方法后执行,每个测试方法后都执行"); } }代码语言:javascript复制package com.artisan.boottest.example; import cn.hutool.core.thread.ThreadUtil; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.time.Duration; /** * @author 小工匠 * @version 1.0 * @description: JUnit断言测试 * @mark: show me the code , change the world */ @Slf4j @ExtendWith(SpringExtension.class) public class AssertTest { // 可以使用fail方法直接断言方法执行失败并输出提示信息。 @Test void failTest() { Assertions.fail("failTest():方法执行失败"); } // 还可以通过assertTrue、assertNull、assertEquals这类方法来断言结果是否符合预期。 @Test void trueTest(){ Assertions.assertTrue(666==666); } @Test void trueFalse(){ Assertions.assertFalse(8888{ String str = null; log.info(str.toLowerCase()); }); } // 还可通过assertTimeout方法断言方法的执行时间。 @Test void timeoutTest(){ Assertions.assertTimeout(Duration.ofMillis(1000),()->{ long sleepTime = 2000; ThreadUtil.sleep(sleepTime); log.info("timeoutTest():休眠{}毫秒",sleepTime); }); } // 或者通过assertAll方法将几个断言结合起来使用,Assertions类中提供的工具方法很多,具体可以参考它的代码。 @Test void assertAllTest(){ Assertions.assertAll(()->{ trueTest(); },()->{ nullTest(); },()->{ equalsTest(); }); } }代码语言:javascript复制package com.artisan.boottest.example; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.test.context.junit.jupiter.SpringExtension; /** * @author 小工匠 * @version 1.0 * @description: 其他常用的注释 * @mark: show me the code , change the world */ @Slf4j @ExtendWith(SpringExtension.class) public class OthreTest { // Spring Boot Test除了上述测试功能,还可以使用@Disabled来禁用某个测试方法 @Test @Disabled("用于测试@Disabled注解") void disabledTest() { log.info("disabledTest():方法被执行"); } // 也可以使用@RepeatedTest来实现循环测试 private static int count = 0; @RepeatedTest(5) void repeatedTest() { count++; log.info("repeatedTest():重复执行第{}次",count); } // 还可以通过@ParameterizedTest来进行参数化测试 @ParameterizedTest @ValueSource(ints = {1,2,3}) public void parameterizedTest(int a){ log.info("parameterizedTest():a={}",a); } }

【三层测试】

代码语言:javascript复制package com.artisan.boottest.project; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.jdbc.Sql; /** * @author 小工匠 * @version 1.0 * @description: Dao层方法测试 * @mark: show me the code , change the world */ @Slf4j @SpringBootTest public class MapperTest { @Autowired private PmsBrandMapper brandMapper; @Test void testGetById(){ long id = 6; PmsBrand pmsBrand = brandMapper.selectByPrimaryKey(id); LOGGER.info("brand name:{}",pmsBrand.getName()); Assertions.assertEquals("小米",pmsBrand.getName()); } }代码语言:javascript复制package com.artisan.boottest.project; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; /** * @author 小工匠 * @version 1.0 * @description: Service层方法测试 * @mark: show me the code , change the world */ @Slf4j @SpringBootTest public class ServiceTest { @Autowired private PmsBrandService brandService; @Test void testGetById(){ long id = 6; PmsBrand pmsBrand = brandService.getBrand(id); log.info("brand name:{}",pmsBrand.getName()); Assertions.assertEquals("小米",pmsBrand.getName()); } }代码语言:javascript复制package com.artisan.boottest.project; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; /** * @author 小工匠 * @version 1.0 * @description: 对于Controller层方法进行测试,有时我们需要模拟请求,使用MockMvc即可 * @mark: show me the code , change the world */ @SpringBootTest @AutoConfigureMockMvc public class ControllerTest { @Autowired private MockMvc mockMvc; @Test void mvcTest() throws Exception { //模拟发送一个请求访问分页查询品牌列表的接口 mockMvc.perform(MockMvcRequestBuilders.get("/brand/list") //设置请求地址 .param("pageNum", "1") //设置请求参数 .param("pageSize", "5")) .andExpect(MockMvcResultMatchers.status().isOk()) //断言返回状态码为200 .andDo(MockMvcResultHandlers.print()) //在控制台打印日志 .andReturn(); //返回请求结果 } }



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3