当前位置: 首页 > article >正文

JUnit5单元测试框架提供的注解

目录

  • 第一章、注释在类上的注解
    • 1.1)JUnit5注释在类上的注解
        • 集成测试:@SpringBootTest
        • 集成测试:@ExtendWith(SpringExtension.class)
        • 单元测试:ExtendWith(MockitoExtension.class)
        • 切片测试:@WebMvcTest和@DataJpaTest
        • <font color=red ><b>手动添加bean到测试上下文:@TestConfiguration
    • 1.2)JUnit4类上的注解简单介绍
        • JUnit4集成测试:@RunWith(SpringJUnit4ClassRunner.class)
        • JUnit4单元测试:@RunWith(MockitoJUnitRunner.class)
  • 第二章、注释在成员变量上的注解
    • 2.1)模拟依赖注入
        • @Mock
        • @MockBean
        • @Spy
    • 2.2)注入真实的bean
        • @Autowired
        • @Captor
    • 2.3)模拟注入被测试类的实例:@InjectMocks
        • @InjectMocks
        • 避免@Autowired和@InjectMock同时使用
  • 第三章、注释在方法上的注解
    • 3.1)标记测试
        • @Test:标记测试方法
        • @ParameterizedTest:参数化测试
        • @RepeatedTest:多次重复进行测试
    • 3.2)标记测试顺序
        • @BeforeEach:指定在每个测试方法运行之前执行的方法。
        • @AfterEach:指定在每个测试方法运行之后执行的方法。
        • @BeforeAll:指定在所有测试方法运行之前执行的方法。
        • @AfterAll:指定在所有测试方法运行之后执行的方法。
    • 3.3)其他注解
        • @Disabled:指定禁用测试方法或测试类。
        • @DisplayName:显示测试名称
        • @Tag:指定测试方法的标签。

友情提醒:

先看文章目录,大致了解文章知识点结构,点击文章目录可直接跳转到文章指定位置。有用记得关注

第一章、注释在类上的注解

1.1)JUnit5注释在类上的注解

集成测试:@SpringBootTest

用于加载整个应用程序上下文的注解

@SpringBootTest注解:

用于指定Spring Boot应用程序的集成测试。
会加载完整的Spring应用程序上下文,并提供Mock Web Environment,包括所有的bean和配置。
通常用于在JUnit 5中进行Spring Boot应用程序的集成测试。

如果测试时不启动Spring上下文可以进行设置:

//@SpringBootTest(webEnvironment = WebEnvironment.NONE)
//禁用Web环境可以将集成测试转换为更接近于单元测试的测试,而不是测试整个Web应用程序。
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
public class MyIntegrationTest {

    @Test
    public void testSomething() {
        // Your test code here
    }
}
集成测试:@ExtendWith(SpringExtension.class)

@ExtendWith(SpringExtension.class)和@SpringBootTest注解结合使用的效果是在JUnit 5测试中启用Spring的测试框架特性,并且会启动完整的Spring应用程序上下文。

如果你只需要启用Spring支持而不需要加载整个应用程序上下文,可以只单独使用@ExtendWith(SpringExtension.class)。而不使用@SpringBootTest注解,这意味着测试中可以使用Spring的依赖注入、自动装配和其他Spring特性,但无法访问完整的Spring Bean和配置。

单元测试:ExtendWith(MockitoExtension.class)

希望在JUnit 5中使用Mockito框架进行单元测试时可以使用@ExtendWith(MockitoExtension.class)来确保正确的测试环境和行为。以便初始化模拟对象并处理严格的存根。这个扩展类类似于JUnit 4中的MockitoJUnitRunner,它可以在测试类中自动初始化模拟对象,并处理严格的存根。

切片测试:@WebMvcTest和@DataJpaTest

@WebMvcTest用于对Spring MVC控制器进行测试,它会限制测试范围,只会加载与Spring MVC相关的组件,例如控制器、拦截器等,而不会加载整个应用程序上下文。这样可以加快测试速度,并且可以专注于对Web层的测试。


@ExtendWith(SpringExtension.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testUserController() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/users"))
                .andExpect(MockMvcResultMatchers.status().isOk());
    }
}

@DataJpaTest用于对JPA持久化层进行测试,它会限制测试范围,只会加载与JPA相关的组件,例如实体类、仓储接口等,而不会加载整个应用程序上下文。这样可以加快测试速度,并且可以专注于对持久化层的测试。

@ExtendWith(SpringExtension.class)
@DataJpaTest
public class UserRepositoryTest {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private UserRepository userRepository;

    @Test
    public void whenFindByName_thenReturnUser() {
        // 测试代码
    }
}
手动添加bean到测试上下文:@TestConfiguration

作用是告诉Spring框架,在测试环境中,这个配置类中定义的bean应该覆盖主应用程序中相同名称的bean,或者提供测试专用的bean定义。

在测试中,定义了一个@TestConfiguration类,通常情况下,它可以放在与被测试类相同的包结构下用于提供测试专用的bean定义。接着通过@Autowired注解将TestConfig配置类引入测试上下文,从而在测试环境中使用其中定义的bean。

    @TestConfiguration
    static class TestConfig {
        @Bean
        public MyService myService() {
            return new MyService();
        }
    }

通过@Autowired注解将TestConfig配置类引入测试上下文

@SpringBootTest
public class IntegrationTestExample {

    @Autowired
    private MyService myService;

    @Test
    public void testIntegration() {
        String result = myService.doSomething();
        assertEquals("expectedResult", result);
    }
    }

1.2)JUnit4类上的注解简单介绍

JUnit4集成测试:@RunWith(SpringJUnit4ClassRunner.class)

注意:在JUnit 5中,不再使用@RunWith注解,而是使用更强大的@ExtendWith注解用于扩展测试的行为

@RunWith注解:

用于指定JUnit 4测试类的运行器。
可以通过@RunWith注解指定不同的测试运行器,
例如Spring提供的SpringJUnit4ClassRunner
通常用于在JUnit 4中加载Spring上下文进行集成测试。
JUnit4单元测试:@RunWith(MockitoJUnitRunner.class)

注意:告诉JUnit在运行测试时使用Mockito运行器,以便正确处理Mockito的注解和行为,通常用于单元测试中,以便对单个组件进行测试而不涉及外部依赖。

@RunWith(MockitoJUnitRunner.class)
public class YourTestClass {

    @Test
    public void yourTestMethod() {
        // Your test method code here
    }
}

第二章、注释在成员变量上的注解

2.1)模拟依赖注入

@Mock

@Mock:用于模拟依赖项,模拟Spring应用程序上下文中的bean。它会创建一个模拟对象,用于替代应用程序上下文中的真实bean。(mock后真实的方法不再调用)不会执行对象的方法(即使方法报错,test只会使用你设置的返回值,不影响流程)

但用Mockito.when(service.方法名(参数)).thenCallRealMethod();还是可以调真实的方法

@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
//模拟注入的依赖项
    @Mock
    private MyDependency myDependency;
    @Test
    public void testQueryUserCount(){
		//待测试的代码。。。
}
}
@MockBean

注解依赖项时,@MockBean注解和@Mock注解的效果是一样的。它们都可以用于模拟依赖项,以便进行单元测试。
@MockBean注解用于模拟Spring应用程序上下文中的bean,并将模拟对象注入到Spring容器中。通常用于模拟service层或repository层的依赖项

@SpringBootTest
public class MyServiceTest {
//MyDependency被用@MockBean注解模拟了,
//可以在不启动Spring Boot应用程序的情况下进行方法的测试。
//也可以使用@Mock注解
    @MockBean
    private MyDependency myDependency;
    @Test
    public void testMyService() {
        // 测试代码
    }
}
@Spy

@Spy:用于模拟依赖项,创建一个真实对象的部分模拟。这意味着对象的实际实现将被保留,但您可以选择模拟特定的方法或行为。即会真实的执行对象的方法(如果方法报错,test直接报错)

但用Mockito.doReturn(“不执行此方法”).when(service).方法名(参数);还是可以不调用真实的方法

public class MyServiceTest {
    @Spy
    private MyDependency myDependency;
    @Test
    public void testSomething() {
        // 在这里使用 myDependency 进行测试
    }
}

2.2)注入真实的bean

@Autowired

用于将实际的Spring bean注入到被测试的类中,以便进行真实的依赖注入。这意味着@Autowired会注入实际的依赖项,而不是模拟对象。

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class MyServiceTest {

    @Autowired
    private MyService myService;

    @Test
    public void testSomething() {
        // 使用myService进行单元测试
    }
}
@Captor

@Captor是Mockito框架中的一个注解,用于捕获方法调用时传入的参数,以便在测试中对参数进行断言或验证。
参数捕获:在测试中,使用@Captor可以捕获方法调用时传递的参数,以便在后续的断言中验证参数的值。
参数验证:通过捕获参数,可以对传递给方法的参数进行验证,确保方法得到了期望的参数值。
灵活性:@Captor提供了一种灵活的方式来处理方法调用时的参数,使得测试更加精确和可靠。

// 示例代码中使用@Captor注解捕获参数
@ExtendWith(MockitoExtension.class)
class ExampleTest {

    @Captor
    private ArgumentCaptor<String> stringCaptor;

    @Mock
    private SomeClass someClass;

    @Test
    void testSomething() {
        // 调用被测试方法
        someClass.doSomething("test");

        //verify(someClass)验证someClass对象的doSomething方法是否被调用
 //@Captor注解创建了一个ArgumentCaptor对象,通过stringCaptor.capture()捕获doSomething方法的参数
        verify(someClass).doSomething(stringCaptor.capture());
        //通过stringCaptor.getValue()获取捕获的参数值
        assertEquals("test", stringCaptor.getValue());
    }
}

2.3)模拟注入被测试类的实例:@InjectMocks

@InjectMocks

用于创建被测试类的实例,注释的是要测试的实现类并注入模拟对象作为其依赖项。通常用于创建被测试类的实例,并将模拟的依赖项注入到被测试类中,以进行单元测试。

@RunWith(MockitoJUnitRunner.class)
public class UserServiceImplTest {
//需要测试的是UserServiceImpl类,使用 @InjectMocks模拟创建实例
    @InjectMocks
    UserServiceImpl userService;
//模拟注入的依赖项
    @Mock
    UserMapper userMapper;

    @Test
    public void testQueryUserCount(){
		//待测试的方法
}
}
避免@Autowired和@InjectMock同时使用

1、在test之前的@BeforeEach注解方法中执行MockitoAnnotations.openMocks(this)
以在每个测试方法之前的初始化操作,包括对Mock对象的初始化。
2、测试的时候要用this.serviceimpl.方法名()测试 否则mock还会使用真实的方法

public class YourTestClass {

    @InjectMocks
    private YourServiceImpl serviceImpl;
    @BeforeEach
    public void init() {
        MockitoAnnotations.openMocks(this);
    }
    // 测试方法
    @Test
    public void testYourServiceMethod() {
        // 调用被测方法
        this.serviceImpl.yourServiceMethod();
        // 断言和验证
        // ...
    }
}

第三章、注释在方法上的注解

3.1)标记测试

@Test:标记测试方法

用于标识单元测试方法。JUnit将会执行被@Test注解标记的方法,并对它们进行断言和验证。JUnit 5中的@Test注解使得编写和执行单元测试变得非常简单和直观。

@ParameterizedTest:参数化测试

通过使用 @ParameterizedTest 注解,可以轻松地在单个测试方法中执行多组输入和预期输出的测试。

@ParameterizedTest 注解标记了 testAddition 方法,该方法使用 @CsvSource 提供了多组输入参数。在这个例子中,@CsvSource 提供了三组输入参数,每组参数包括两个加数和预期的结果。在测试方法中,使用提供的输入参数进行计算,并使用断言来验证计算结果是否符合预期。

public class ParameterizedTestExample {

    @ParameterizedTest
    @CsvSource({ "1, 1, 2", "2, 3, 5", "5, 5, 10" })
    void testAddition(int a, int b, int expectedResult) {
        Calculator calculator = new Calculator();
        int result = calculator.add(a, b);
//expectedResult期望结果,result实际的计算结果,Lambda表达式,用于生成断言失败时的错误消息。
assertEquals(expectedResult, result, () -> a + " + " + b + " should equal " + expectedResult);
    }
}
@RepeatedTest:多次重复进行测试

@RepeatedTest 注解用于指定重复测试

public class RepeatedTestExample {
//下面的测试方法将被重复执行五次
    @RepeatedTest(5)
    void repeatedTest() {
        // 测试逻辑
        assertTrue(true);
    }
}

3.2)标记测试顺序

@BeforeEach:指定在每个测试方法运行之前执行的方法。

@BeforeEach注解用于标记一个方法,@BeforeEach执行多次,在每个测试方法执行之前都会被执行。这样可以确保在每个测试方法执行前都有一致的初始化操作。

public class ExampleTest {

    private String message;

    @BeforeEach
    public void init() {
        message = "Hello, World!";
    }

    @Test
    public void testMessage() {
        assertEquals("Hello, World!", message);
    }
}
@AfterEach:指定在每个测试方法运行之后执行的方法。

使用@AfterEach注解的目的是确保在每个测试方法执行之后都有一致的清理操作。这有助于避免测试方法之间的相互影响,以及确保每个测试方法都在一个干净的状态下执行。

public class ExampleTest {

    private String message;

    @AfterEach
    public void cleanUp() {
        message = null;
    }

    @Test
    public void testMessage() {
        message = "Hello, World!";
        assertEquals("Hello, World!", message);
    }
}
@BeforeAll:指定在所有测试方法运行之前执行的方法。

@BeforeAll只在第一次运行测试方法时执行一次,后面都不再执行。这意味着它用于执行一次性的全局初始化操作
而@BeforeEach会执行多次,每次运行测试方法都会执行。

public class ExampleTest {

    private static String message;

    @BeforeAll
    public static void init() {
        message = "Hello, World!";
    }

    @Test
    public void testMessage() {
        assertEquals("Hello, World!", message);
    }
}
@AfterAll:指定在所有测试方法运行之后执行的方法。

@AfterAll注解标记的方法在整个测试类中的所有测试方法都执行之后执行一次,用于执行全局的清理操作。

如果我有4个测试方法,执行了3个,这时候是不会触发@AfterAll注解的方法的。

public class ExampleTest {

    private static String message;

    @AfterAll
    public static void cleanUp() {
        message = null;
    }

    @Test
    public void testMessageIsNull() {
        assertEquals(null, message);
    }
}

3.3)其他注解

@Disabled:指定禁用测试方法或测试类。

用于禁用单个测试方法或测试类,这意味着被注解的测试方法或测试类将不会被执行。这在临时禁用某些测试时非常有用,例如当测试方法出现问题或需要进行调整时。

public class ExampleTest {

    @Disabled("This test is currently disabled")
    @Test
    void disabledTest() {
        // Test logic that should be disabled
    }

    @Test
    void enabledTest() {
        // Test logic that should be enabled
    }
}
@DisplayName:显示测试名称

@DisplayName(“Custom Test Name”) 用于指定测试方法的显示名称为 “Custom Test Name”。这个显示名称将会在测试报告、IDE中的测试运行结果以及构建工具(如Gradle、Maven)生成的测试报告中显示。

public class DisplayNameExample {

    @Test
    @DisplayName("Custom Test Name")
    void customTestName() {
        // 测试逻辑
        assertEquals(2, 1 + 1);
    }
}
@Tag:指定测试方法的标签。

在JUnit 5中,使用@Tag注解在测试方法添加标签,也可以为整个测试类添加@Tag注解标签,以便更好地组织和筛选测试。

@Tag("development")
public class ExampleTest {
    
    @Test
    @Tag("unit")
    void test1() {
        // 测试方法1的测试逻辑
    }
    
    @Test
    @Tag("integration")
    void test2() {
        // 测试方法2的测试逻辑
    }
}

通过为测试方法或测试类添加标签,可以更轻松地选择性地运行特定标签的测试,或者排除特定标签的测试。使用Maven在命令行中:

mvn test -Dgroups=tagName
//实例:
mvn test -Dgroups=unit

通过Maven Surefire插件配置选择性运行标签的测试:在maven-surefire-plugin的groups,如果要运行标签为"tagName"的测试,可以将groups参数设置为"tagName"。再执行mvn test命令将会根据配置运行具有指定标签的测试。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.0.0-M5</version>
            <configuration>
                <groups>tagName</groups>
            </configuration>
        </plugin>
    </plugins>
</build>

http://www.kler.cn/a/231692.html

相关文章:

  • 物联网——UNIX时间戳、BKP备份寄存器、RTC时钟
  • 计算机视觉和机器人技术中的下一个标记预测与视频扩散相结合
  • Java基础-Java中的常用类(上)
  • 深度学习transformer
  • 深入理解 C++ 二叉树
  • ARM 汇编指令
  • Django学习记录01
  • 如何使用websocket
  • LLVM实战之opt工具的使用
  • 每日一练 | 华为认证真题练习Day182
  • 大厂聚合支付系统架构演进(下)
  • 【开源】基于JAVA+Vue+SpringBoot的新能源电池回收系统
  • 【C#】Xasset加载资源模块
  • 中科大计网学习记录笔记(四):Internet 和 ISP | 分组延时、丢失和吞吐量
  • nodeJS 的 npm 设置国内高速镜像之淘宝镜像的方法
  • 小白水平理解面试经典题目LeetCode 71. Simplify Path【Stack类】
  • Java-加解密-roadmap
  • 16:定时器和计数器
  • 【Ubuntu】安装filebeat
  • SpringCache缓存快速实现注解
  • 在angular12中proxy.conf.json中配置详解
  • 【Git版本控制 03】远程操作
  • 2024年的VUE2下的无效指令npm install --save vue-i18n
  • ChatGPT高效提问—prompt常见用法(续篇三)
  • 超级干货:ArcGIS的那些花样技巧
  • 容器基础知识:容器和虚拟化的区别