springboot中junit回滚

本文介绍如何在SpringBoot项目中使用JUnit进行单元测试,并确保测试操作不会影响到实际数据库数据。通过具体示例展示了如何设置测试环境、编写测试用例以及使用@Transactional和@Rollback注解来实现数据库操作的回滚。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

springboot中使用junit编写单元测试,并且测试结果不影响数据库。

pom引入依赖

如果是IDE生成的项目,该包已经默认引入。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

数据库原始数据

img_bb46e7b6978d47250653ecd74d2d8b39.png
原始数据

编写单元测试

package com.mos.quote;

import com.mos.quote.model.Area;
import com.mos.quote.service.IAreaService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class QuoteApplicationTests {

    @Autowired
    private IAreaService areaService;

    @Test
    public void contextLoads() {
    }

    @Test
    public void testUpdate(){
        Area area = new Area();
        area.setCode("001003");
        area.setName("洛阳市");
        Integer result = areaService.update(area);
        Assert.assertEquals(1, (long)result);
    }

    @Test
    @Transactional
    @Rollback
    public void testUpdate4Rollback(){
        Area area = new Area();
        area.setCode("001001");
        area.setName("郑州市123");
        Integer result = areaService.update(area);
        Assert.assertEquals(1, (long)result);
    }

}

结果数据

img_8dd7092eaf3448efe3c16a8070d8284a.png
结果数据

结论

可以看出code=001001的数据没有更改,而code=001003的数据修改成功。回头看代码:
@Transactional表示该方法整体为一个事务,
@Rollback表示事务执行完回滚,支持传入一个参数value,默认true即回滚,false不回滚。
该注解一样支持对类的注解,若如此做,对整个class的方法有效。

img_c37a08e75fce8cedfe10850d6335050c.png
注解在class上
<think>嗯,用户想了解在Spring Boot中使用JUnit进行单元测试的最佳实践。首先,我需要回忆一下Spring Boot测试相关的知识,尤其是结合JUnit的部分。记得用户提供的引用里提到了@SpringBootTest、@MockBean这些注解,还有Mockito的使用,这些应该是关键点。 用户之前的问题是关于Spring BootJUnit测试,现在需要最佳实践。最佳实践通常包括测试分层、模拟依赖、使用合适的注解、断言库的选择,以及测试配置的管理。我需要整理这些点,结合引用中的信息来组织回答。 首先,应该提到依赖配置,确保build.gradle或pom.xml中有正确的依赖,比如spring-boot-starter-test,它默认包含了JUnit Jupiter和Mockito等。引用2中提到了Gradle的配置,可以引用这个部分。 然后,测试分层,分Controller、Service、Repository层的测试。对于Service层,使用@MockBean来模拟Repository,如引用1中的例子。Controller层测试可能需要使用MockMvc,引用3或4中是否有相关内容?可能需要提到@WebMvcTest来切片测试Controller。 接着,常用的注解,比如@SpringBootTest、@WebMvcTest、@DataJpaTest,这些是Spring Boot提供的测试切片,可以优化测试速度。引用4提到@ExtendWith,但@SpringBootTest已经包含,所以不需要额外添加。 然后,模拟和断言部分,使用Mockito的when和thenReturn来模拟依赖,断言用AssertJ,因为Spring Boot Test默认集成它,如引用3中的示例可能用到了断言。 测试配置优化部分,比如使用@Mock代替@MockBean当不需要Spring上下文时,可以加快测试速度。还有事务回滚,使用@Transactional避免污染数据库,引用4可能提到事务相关的内容吗? JUnit 5的特性,比如@DisplayName给测试方法起别名,动态测试等,引用4提到了JUnit5的断言机制,可能需要强调使用Jupiter的API。 示例部分,需要给出Service层和Controller层的测试代码示例,参考引用1和3中的例子,比如UserService的测试,用@MockBean UserRepository,然后调用服务方法并断言结果。 最后,注意事项,比如避免直接测试私有方法,测试独立性,合理使用切片测试,这些是常见的最佳实践。可能引用3或4中提到过测试的独立性和可控性。 相关问题部分,需要生成与Spring Boot测试相关的问题,比如如何测试Repository层,JUnit5与4的区别,MockMvc的使用,或者如何集成测试,这些都能帮助用户进一步学习。 需要确保回答结构清晰,分点说明,每个部分都有示例代码和引用标记。比如在依赖配置部分引用引用2,模拟和断言引用1和3,测试配置优化引用4等。同时,检查是否符合用户的要求,比如使用中文,LaTeX格式正确,生成相关问题等。</think>### Spring Boot中使用JUnit进行单元测试的最佳实践 #### 一、依赖配置 在`build.gradle`或`pom.xml`中添加测试依赖: ```groovy dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } ``` 需确保使用`@SpringBootTest`时会自动包含JUnit Jupiter、Mockito和AssertJ等工具[^2][^4]。 #### 二、测试分层策略 1. **Service层测试** 使用`@MockBean`模拟依赖的Repository,通过`@SpringBootTest`加载部分上下文: ```java @SpringBootTest class UserServiceTest { @Autowired private UserService userService; @MockBean private UserRepository userRepository; @Test void testFindUserById() { when(userRepository.findById(1L)).thenReturn(new User(1L, "test")); User result = userService.getUserById(1L); assertThat(result.getName()).isEqualTo("test"); } } ``` 通过`when().thenReturn()`控制模拟对象行为[^1][^3]。 2. **Controller层测试** 使用`@WebMvcTest`进行切片测试,仅加载Web相关组件: ```java @WebMvcTest(UserController.class) class UserControllerTest { @Autowired private MockMvc mockMvc; @MockBean private UserService userService; @Test void testGetUser() throws Exception { when(userService.getUserById(1L)).thenReturn(new User(1L, "test")); mockMvc.perform(get("/users/1")) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("test")); } } ``` #### 三、关键注解与机制 | 注解 | 作用 | |------------------|--------------------------------------------------------------------| | `@SpringBootTest`| 加载完整或部分Spring上下文,适用于集成测试[^4] | | `@MockBean` | 替换Spring上下文中的Bean为Mock对象,支持Service层隔离测试[^1] | | `@Transactional` | 测试后自动回滚数据库操作,避免数据污染 | | `@DisplayName` | 为测试方法添加可读性更强的描述(JUnit5特性) | #### 四、优化实践 1. **减少上下文加载** - 优先使用`@WebMvcTest`、`@DataJpaTest`等切片测试注解 - 避免不必要的`@SpringBootTest`全量加载 2. **断言选择** 使用AssertJ增强断言可读性: ```java assertThat(userList).hasSize(3).extracting("name").contains("Alice", "Bob"); ``` 3. **动态测试** JUnit5支持动态生成测试用例: ```java @TestFactory Stream<DynamicTest> dynamicTests() { return Stream.of("A", "B").map(text -> dynamicTest("Test for " + text, () -> assertThat(text).isUpperCase())); } ``` #### 五、常见问题处理 - **测试独立性**:每个测试方法应重置Mock状态,可通过`@AfterEach`清理 - **性能优化**:使用`@Mock`代替`@MockBean`当不需要Spring上下文时 - **配置隔离**:在`src/test/resources`中放置专属`application-test.yml`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值