首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

通过AI自动生成springboot的CRUD以及单元测试与压力测试源码(完整版)

  • 25-04-24 13:42
  • 2417
  • 10093
blog.csdn.net

本篇文章分为三个部分,即:
通过AI自动生成springboot的CRUD以及单元测试与压力测试源码(一)
通过AI自动生成springboot的CRUD以及单元测试与压力测试源码(二)
通过AI自动生成springboot的CRUD以及单元测试与压力测试源码(完整版)


文章目录

  • 一、AICoder插件简介
  • 二、环境准备
  • 三、自动生成CRUD代码
    • 1、创建SpringBoot项目
    • 2、通过AiCoder生成代码
  • 四、生成UserController的单元测试类
  • 五、生成UserController压力测试类
  • 六、验证
  • 七、Aicoder其他的功能
    • 1、针对某个方法生成单元测试
    • 2、针对代码生成注释
    • 3、代码解释
    • 4、缺陷检测


在现代软件开发中,快速生成高质量的代码是提高开发效率的关键。SpringBoot作为Java生态中最流行的框架之一,广泛应用于企业级应用开发。然而,手动编写CRUD(创建、读取、更新、删除)操作及其单元测试和压力测试代码往往耗时且容易出错。本文将介绍如何通过AICoder插件自动生成SpringBoot技术栈的CRUD代码及其单元测试和压力测试源码,从而大幅提升开发效率。

本示例使用的是AICoder插件,同类的还有如下所示:

  • 代码补全与生成: GitHub Copilot、Tabnine
  • 代码质量分析: SonarQube、DeepCode
  • 代码生成与模板化: JHipster、Spring AI
  • 代码重构与优化: IntelliJ IDEA、Eclipse Code Recommenders
  • 文档生成: Javadoc AI、Documatic
  • 测试代码生成: Diffblue Cover、EvoSuite
  • 代码翻译与迁移: Java to Kotlin 转换器、TransCoder

如果你需要一个功能全面、易于集成的工具,GitHub Copilot 和 IntelliJ IDEA 是最佳选择。它们可以帮助你完成从代码补全到重构的整个开发流程。

一、AICoder插件简介

AICoder是一款基于人工智能的代码生成工具,能够根据开发者的需求自动生成高质量的代码。它支持多种编程语言和框架,包括Java、SpringBoot、Python等。通过AICoder,开发者可以快速生成CRUD操作、单元测试和压力测试代码,减少手动编写代码的工作量。

二、环境准备

在开始之前,确保你已经安装了以下工具:

  • JDK 1.8或更高版本
  • Maven 3.x
  • IntelliJ IDEA或VS code
  • AICoder插件(可通过IDE插件市场安装)
  • mysql

三、自动生成CRUD代码

1、创建SpringBoot项目

在IntelliJ IDEA创建一个maven项目,其他的都可以不需要。目录结构如下:
在这里插入图片描述
上图中的htmlReport是覆盖率测试的报告,初始创建的时候是没有了。

2、通过AiCoder生成代码

在aicoder的对话框内输入指令“生成以springboot、mysql技术的curd”,然后aicoder就自动的开始生成代码来,示例如下图。
在这里插入图片描述
生成的代码如下

  • User 实体类
package com.example.demo.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private int age;
    private String email;

    // 无参构造函数
    public User() {}

    // 有参构造函数
    public User(Long id, String name, int age, String email) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.email = email;
    }

    // Getter 和 Setter 方法
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • UserRepository 接口
package com.example.demo.repository;

import com.example.demo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • UserService 服务类
package com.example.demo.service;

import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    /**
     * 创建用户
     * @param user 用户对象
     * @return 创建的用户对象
     */
    public User createUser(User user) {
        return userRepository.save(user);
    }

    /**
     * 获取所有用户
     * @return 用户列表
     */
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    /**
     * 通过ID获取用户
     * @param id 用户ID
     * @return 可选的用户对象
     */
    public Optional<User> getUserById(Long id) {
        return userRepository.findById(id);
    }

    /**
     * 更新用户
     * @param id 用户ID
     * @param user 更新后的用户对象
     * @return 更新后的用户对象
     */
    public Optional<User> updateUser(Long id, User user) {
        Optional<User> existingUser = userRepository.findById(id);
        if (existingUser.isPresent()) {
            User updatedUser = existingUser.get();
            updatedUser.setName(user.getName());
            updatedUser.setAge(user.getAge());
            updatedUser.setEmail(user.getEmail());
            return Optional.of(userRepository.save(updatedUser));
        }
        return Optional.empty();
    }

    /**
     * 删除用户
     * @param id 用户ID
     */
    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • UserController 控制器类
package com.example.demo.controller;

import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;

    /**
     * 创建用户
     * @param user 用户对象
     * @return 创建的用户对象
     */
    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.createUser(user);
    }

    /**
     * 获取所有用户
     * @return 用户列表
     */
    @GetMapping
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }

    /**
     * 通过ID获取用户
     * @param id 用户ID
     * @return 用户对象
     */
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        Optional<User> user = userService.getUserById(id);
        if (user.isPresent()) {
            return ResponseEntity.ok(user.get());
        } else {
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 更新用户
     * @param id 用户ID
     * @param user 更新后的用户对象
     * @return 更新后的用户对象
     */
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        Optional<User> updatedUser = userService.updateUser(id, user);
        if (updatedUser.isPresent()) {
            return ResponseEntity.ok(updatedUser.get());
        } else {
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 删除用户
     * @param id 用户ID
     * @return 删除操作的状态
     */
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return ResponseEntity.noContent().build();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 应用启动类
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 应用配置文件 application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/demo_db
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 依赖管理 pom.xml
<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-jpaartifactId>
    dependency>
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <scope>runtimescope>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
dependencies>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 数据库表结构
CREATE DATABASE demo_db;

USE demo_db;

CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    age INT NOT NULL,
    email VARCHAR(255) NOT NULL
);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 运行应用
    确保 MySQL 服务已经启动,并且 demo_db 数据库已经创建。
    运行 Spring Boot 应用。
    使用 Postman 或其他 HTTP 客户端测试 CRUD 操作。

  • 测试 CRUD 操作

创建用户:  
POST /users
Content-Type: application/json

{
  "name": "张三",
  "age": 30,
  "email": "[email protected]"
}
获取所有用户:  
GET /users
通过ID获取用户:  
GET /users/1
更新用户:  
PUT /users/1
Content-Type: application/json

{
  "name": "李四",
  "age": 35,
  "email": "[email protected]"
}
删除用户:  
DELETE /users/1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

通过以上的步骤就可以完成了代码生成,根据自己的需要进行局部调整就可以正式的使用了。

四、生成UserController的单元测试类

在aicoder的对话框内输入“生成UserController的单元测试类”指令,其就可以自动的生成了代码,示例如下:
在这里插入图片描述
生成的源码如下。

  • 添加测试依赖
    确保你的 pom.xml 文件包含以下测试依赖:
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-testartifactId>
    <scope>testscope>
dependency>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 创建单元测试类
    以下生成的单元测试类修改了包名称。
package com.win.test;

import com.win.bean.User;
import com.win.control.UserController;
import com.win.service.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import java.util.Arrays;
import java.util.Optional;

@Nested
@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    private User user1;
    private User user2;

    /**
     * 在每个测试方法执行之前运行的设置方法。
     * 用于初始化测试所需的用户对象。
     */
    @BeforeEach
    public void setUp() {
        // 创建用户1,ID为1,姓名为"alan",年龄为18,邮箱为"[email protected]"
        user1 = new User(1L, "alan", 18, "[email protected]");

        // 创建用户2,ID为2,姓名为"alanchan",年龄为18,邮箱为"[email protected]"
        user2 = new User(2L, "alanchan", 18, "[email protected]");
    }

    /**
     * 测试获取所有用户的方法。
     */
    @Test
    public void testGetAllUsers() throws Exception {
        // 模拟 userService 的行为
        Mockito.when(userService.getAllUsers()).thenReturn(Arrays.asList(user1, user2));

        // 发送 GET 请求并验证响应
        mockMvc.perform(MockMvcRequestBuilders.get("/users")
                        .accept(MediaType.APPLICATION_JSON))
                // 验证响应状态码为 200 OK
                .andExpect(MockMvcResultMatchers.status().isOk())
                // 验证响应内容为 JSON 格式,包含两个用户对象
                .andExpect(MockMvcResultMatchers.content().json("[{\"id\":1,\"name\":\"alan\",\"age\":18,\"email\":\"[email protected]\"},{\"id\":2,\"name\":\"alanchan\",\"age\":18,\"email\":\"[email protected]\"}]"
                ));
    }

    /**
     * 测试 getUserById 方法的单元测试。
     * 该测试方法使用 Mockito 模拟 userService 的行为,并使用 MockMvc 发送 GET 请求以验证响应。
     * 测试包括两个场景:存在用户和不存在用户。
     */
    @Test
    public void testGetUserById() throws Exception {
        // 模拟 userService 的行为
        Mockito.when(userService.getUserById(1L)).thenReturn(Optional.of(user1));

        // 发送 GET 请求并验证响应
        mockMvc.perform(MockMvcRequestBuilders.get("/users/1")
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.content().json("{" +
                        "\"id\":1," +
                        "\"name\":\"alan\"," +
                        "\"age\":18," +
                        "\"email\":\"[email protected]\"}"));

        // 测试不存在的用户
        Mockito.when(userService.getUserById(999L)).thenReturn(Optional.empty());

        // 发送 GET 请求并验证响应
        mockMvc.perform(MockMvcRequestBuilders.get("/users/999")
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(MockMvcResultMatchers.status().isNotFound());
    }

    /**
     * 测试创建用户的方法。
     * 该测试方法使用Mockito模拟userService的行为,并使用MockMvc发送POST请求,验证响应状态和内容。
     */
    @Test
    public void testCreateUser() throws Exception {
        // 创建一个用户对象,不包含id
        User user = new User(null, "alanchanchn", 20, "[email protected]");

        // 模拟 userService 的行为
        // 当调用 userService.createUser(user) 时,返回一个id为3的用户对象
        User createdUser = new User(3L, "alanchanchn", 20, "[email protected]");
        Mockito.when(userService.createUser(user)).thenReturn(createdUser);

        // 发送 POST 请求并验证响应
        mockMvc.perform(MockMvcRequestBuilders.post("/users")
                        .content("{\"name\":\"alanchanchn\",\"age\":20,\"email\":\"[email protected]\"}")
                        .contentType(MediaType.APPLICATION_JSON)
                        .accept(MediaType.APPLICATION_JSON))
                // 验证响应状态为200 OK
                .andExpect(MockMvcResultMatchers.status().isOk())
                // 验证响应内容是否符合预期的JSON格式
                .andExpect(MockMvcResultMatchers.content().json("{" +
                        "\"id\":3," +
                        "\"name\":\"alanchanchn\"," +
                        "\"age\":20," +
                        "\"email\":\"[email protected]\"" +
                        "}"));
    }

    /**
     * 测试 updateUser 方法的单元测试。
     * 该测试包括两个场景:更新存在的用户和更新不存在的用户。
     */
    @Test
    public void testUpdateUser() throws Exception {
        // 创建一个用户对象,不包含id
        User userToUpdate = new User(null, "alanchanchn", 20, "[email protected]");

        // 模拟 userService 的行为
        // 当调用 userService.updateUser(1L, userToUpdate) 时,返回一个id为1的用户对象
        User updatedUser = new User(1L, "alanchanchn", 20, "[email protected]");
        Mockito.when(userService.updateUser(1L, userToUpdate)).thenReturn(updatedUser);

        // 发送 PUT 请求并验证响应
        mockMvc.perform(MockMvcRequestBuilders.put("/users/1")
                        .content("{\"name\":\"alanchanchn\",\"age\":20,\"email\":\"[email protected]\"}")
                        .contentType(MediaType.APPLICATION_JSON)
                        .accept(MediaType.APPLICATION_JSON))
                // 验证响应状态为200 OK
                .andExpect(MockMvcResultMatchers.status().isOk())
                // 验证响应内容是否符合预期的JSON格式
                .andExpect(MockMvcResultMatchers.content().json("{" +
                        "\"id\":1," +
                        "\"name\":\"alanchanchn\"," +
                        "\"age\":20," +
                        "\"email\":\"[email protected]\"}"));

        // 测试不存在的用户
        Mockito.when(userService.updateUser(999L, userToUpdate)).thenReturn(null);

        // 发送 PUT 请求并验证响应,期望返回 404 Not Found
        mockMvc.perform(MockMvcRequestBuilders.put("/users/999")
                        .content("{\"name\":\"alanchanchn\",\"age\":20,\"email\":\"[email protected]\"}")
                        .contentType(MediaType.APPLICATION_JSON)
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(MockMvcResultMatchers.status().isNotFound());
    }

    /**
     * 测试删除用户的功能。
     * 该测试方法使用Mockito模拟userService的行为,并使用MockMvc发送HTTP DELETE请求。
     * 测试包括删除存在的用户和删除不存在的用户。
     */
    @Test
    public void testDeleteUser() throws Exception {
        // 模拟 userService 的行为
        Mockito.doNothing().when(userService).deleteUser(1L);

        // 发送 DELETE 请求并验证响应
        mockMvc.perform(MockMvcRequestBuilders.delete("/users/1")
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(MockMvcResultMatchers.status().isNoContent());

        // 测试不存在的用户
        Mockito.doNothing().when(userService).deleteUser(999L);

        // 发送 DELETE 请求并验证响应
        mockMvc.perform(MockMvcRequestBuilders.delete("/users/999")
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(MockMvcResultMatchers.status().isNoContent());
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187

五、生成UserController压力测试类

在aicoder的对话框内输入"生成UserController压力测试类"指令,其就可以自动的生成代码了,示例如下。
在这里插入图片描述
更改了生成源码所在的包。

package com.win.test;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.win.bean.User;
import com.win.control.UserController;
import com.win.service.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest(UserController.class)
public class UserControllerStressTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    private final int threadCount = 1000; // 并发线程数
    private final int requestCount = 10000; // 总请求数

    @BeforeEach
    public void setUp() {
        // 模拟 userService 的行为
        List<User> users = new ArrayList<>();
        users.add(new User(1L, "Alice",18, "[email protected]"));
        users.add(new User(2L, "Bob",20, "[email protected]"));
        when(userService.getAllUsers()).thenReturn(users);
        when(userService.getUserById(1L)).thenReturn(Optional.ofNullable(users.get(0)));
        when(userService.getUserById(2L)).thenReturn(Optional.ofNullable(users.get(1)));
    }

    @Test
    public void testGetAllUsersStress() throws Exception {
        AtomicInteger successCount = new AtomicInteger(0);
        AtomicInteger failureCount = new AtomicInteger(0);
        CountDownLatch latch = new CountDownLatch(requestCount);

        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

        for (int i = 0; i < requestCount; i++) {
            executorService.submit(() -> {
                try {
                    MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/users"))
                            .andExpect(status().isOk())
                            .andReturn();

                    successCount.incrementAndGet();
                } catch (Exception e) {
                    failureCount.incrementAndGet();
                } finally {
                    latch.countDown();
                }
            });
        }

        latch.await();
        executorService.shutdown();

        System.out.println("成功请求: " + successCount.get());
        System.out.println("失败请求: " + failureCount.get());
    }

    @Test
    public void testGetUserByIdStress() throws Exception {
        AtomicInteger successCount = new AtomicInteger(0);
        AtomicInteger failureCount = new AtomicInteger(0);
        CountDownLatch latch = new CountDownLatch(requestCount);

        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

        for (int i = 0; i < requestCount; i++) {
            executorService.submit(() -> {
                try {
                    MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/users/1"))
                            .andExpect(status().isOk())
                            .andReturn();
                    successCount.incrementAndGet();
                } catch (Exception e) {
                    failureCount.incrementAndGet();
                } finally {
                    latch.countDown();
                }
            });
        }

        latch.await();
        executorService.shutdown();

        System.out.println("成功请求: " + successCount.get());
        System.out.println("失败请求: " + failureCount.get());
    }

    @Test
    public void testCreateUserStress() throws Exception {
        AtomicInteger successCount = new AtomicInteger(0);
        AtomicInteger failureCount = new AtomicInteger(0);
        CountDownLatch latch = new CountDownLatch(requestCount);

        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

        for (int i = 0; i < requestCount; i++) {
            final int index = i; // 将 i 复制为 final 变量
            executorService.submit(() -> {
                try {
                    User user = new User((long) (index + 1000), "User" + index,11, "user" + index + "@example.com");
                    MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/users")
                                    .contentType("application/json")
                                    .content(objectMapper.writeValueAsString(user)))
                            .andExpect(status().isOk())
                            .andReturn();
                    successCount.incrementAndGet();
                } catch (Exception e) {
                    failureCount.incrementAndGet();
                } finally {
                    latch.countDown();
                }
            });
        }

        latch.await();
        executorService.shutdown();

        System.out.println("成功请求: " + successCount.get());
        System.out.println("失败请求: " + failureCount.get());
    }

    @Test
    public void testUpdateUserStress() throws Exception {
        AtomicInteger successCount = new AtomicInteger(0);
        AtomicInteger failureCount = new AtomicInteger(0);
        CountDownLatch latch = new CountDownLatch(requestCount);

        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

        for (int i = 0; i < requestCount; i++) {
            final int index = i; // 将 i 复制为 final 变量
            executorService.submit(() -> {
                try {
                    User user = new User((long) (index + 1000), "User" + index, 12,"user" + index + "@example.com");
                    MvcResult result = mockMvc.perform(MockMvcRequestBuilders.put("/users/1")
                                    .contentType("application/json")
                                    .content(objectMapper.writeValueAsString(user)))
                            .andExpect(status().isOk())
                            .andReturn();
                    successCount.incrementAndGet();
                } catch (Exception e) {
                    failureCount.incrementAndGet();
                } finally {
                    latch.countDown();
                }
            });
        }

        latch.await();
        executorService.shutdown();

        System.out.println("成功请求: " + successCount.get());
        System.out.println("失败请求: " + failureCount.get());
    }

    @Test
    public void testDeleteUserStress() throws Exception {
        AtomicInteger successCount = new AtomicInteger(0);
        AtomicInteger failureCount = new AtomicInteger(0);
        CountDownLatch latch = new CountDownLatch(requestCount);

        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

        for (int i = 0; i < requestCount; i++) {
            executorService.submit(() -> {
                try {
                    MvcResult result = mockMvc.perform(MockMvcRequestBuilders.delete("/users/1"))
                            .andExpect(status().isOk())
                            .andReturn();
                    successCount.incrementAndGet();
                } catch (Exception e) {
                    failureCount.incrementAndGet();
                } finally {
                    latch.countDown();
                }
            });
        }

        latch.await();
        executorService.shutdown();

        System.out.println("成功请求: " + successCount.get());
        System.out.println("失败请求: " + failureCount.get());
    }

    private ObjectMapper objectMapper = new ObjectMapper();
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211

六、验证

正常功能验证,比较容易,不再赘述,基本上不会出错。
单元测试的用例可能需要调整一下,因为其没有有参构造函数。
只要单元测试通过,压力测试结果会通过。
示例如下,本示例使用的覆盖率运行,能看到单元测试的覆盖率。
单元测试覆盖率报告可以导出成html文件,可以自己试一试。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
压力测试,运行的时候会自动记录成功与错误的记录数,以及可以观察一下运行机器的网络、cpu、内存以及硬盘的使用情况,当然如果更专业的压力测试则是使用jmeter等专业的软件。

七、Aicoder其他的功能

1、针对某个方法生成单元测试

在这里插入图片描述
点击单元测试,在AiCoder的面板上就生成了该方法对应的单元测试类,示例如下
在这里插入图片描述

2、针对代码生成注释

示例如下
在这里插入图片描述

3、代码解释

点击代码解释,示例如下
在这里插入图片描述

4、缺陷检测

点击缺陷检测,示例如下
在这里插入图片描述

以上通过AICoder插件,我们可以快速生成SpringBoot技术栈的CRUD代码及其单元测试和压力测试源码。本示例没有生产前端代码,也可以根据需要进行生成,不再赘述。这不仅大大提高了开发效率,还确保了代码的质量和一致性。希望本文能帮助你更好地利用AICoder插件,提升你的开发体验。

科技赋予美好生活能力
微信名片
注:本文转载自blog.csdn.net的一瓢一瓢的饮 alanchanchn的文章"https://blog.csdn.net/chenwewi520feng/article/details/146262465"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

127
测试
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top