V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cweijan
V2EX  ›  Java

快速测试 SpringMvc 接口, 跟 PostMan 说再见!

  •  
  •   cweijan ·
    cweijan · 2020-06-01 14:52:05 +08:00 · 4179 次点击
    这是一个创建于 1621 天前的主题,其中的信息可能已经有所发展或是发生改变。

    做 Java 开发 3 年了, 每次想要测试开发完的接口总是有点头疼, 要复制 url, 又要写测试参数, 为了解决这些烦恼, 我开发了一个快速测试的工具, 直接面向 controller 测试. 项目地址 https://github.com/cweijan/http-test

    example:

    1. 增加依赖
    <dependency>
        <groupId>io.github.cweijan</groupId>
        <artifactId>http-test</artifactId>
        <version>0.0.3</version>
        <scope>test</scope>
    </dependency>
    
    1. 假设有以下 controller, 启动 springboot 应用
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        private final UserService userService;
    
        public UserController(UserService userService) {
            this.userService = userService;
        }
    
        @PostMapping("/save")
        public UserVo saveUser(@RequestBody SaveUserDTO saveuserDTO) {
            return userService.saveUser(saveuserDTO);
        }
    
        @PostMapping("/update")
        public UserVo updateUser(@RequestBody UpdateUserDTO updateuserDTO) {
            return userService.updateUser(updateuserDTO);
        }
      
        @GetMapping("/{userId}")
        public UserVO getUser(@PathVariable Integer userId) {
            return userService.getUser(userId);
        }
    
        @DeleteMapping("/{userId}")
        public void deleteByUserId(@PathVariable Integer userId) {
            userService.deleteByUserId(userId);
        }
    
    }
    
    1. 创建测试用例, 开始测试
    import io.github.cweijan.mock.Asserter;
    import io.github.cweijan.mock.jupiter.HttpTest;
    import io.github.cweijan.mock.request.Generator;
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.BeforeAll;
    
    import javax.annotation.Resource;
    
    @HttpTest(host = "localhost",port = 8080)
    public class UserControllerTest {
    
        //仅支持注入 controller 和 feignClient
        @Resource
        private UserController userController;
    
        @BeforeAll
        public static void addToken(){
            //配置全局拦截器
            Mocker.addRequestInterceptor(template -> {
                template.header("token","c2f678d4873c472c8f99940e8cf39fe4");
            });
        }
    
        // 注意, 必须使用 junit5: org.junit.jupiter.api.Test
        @Test
        void saveUser() {
    
            //创建 mock 数据
            SaveUserDTO saveUserDTO = Generator.request(SaveUserDTO.class);
            // 当调用方法时会直接发送 http 请求
            UserVo userVo=userController.saveUser(saveUserDTO);
    
            UserVO user = userController.getUser(userVo.getId());
    
            Asserter.assertSame(userVo,user);
    
            userController.deleteByUserId(userVo.getId());
            
        }       
    
    }
    

    SpringBootTest 也可以实现该测试, 但需要启动 spring 容器, 耗时实在太久, 该方式毫秒级即可运行完测试.

    19 条回复    2020-06-02 16:15:52 +08:00
    zoharSoul
        1
    zoharSoul  
       2020-06-01 15:09:04 +08:00
    感觉挺有意思的...
    gengz
        2
    gengz  
       2020-06-01 15:11:10 +08:00   ❤️ 2
    我选择 swagger
    zhazi
        3
    zhazi  
       2020-06-01 15:13:00 +08:00 via Android
    这东西需要启动项目,就是个 httpclient,完全没达到测试的目的,不能保证可重复性,测试完数据库一堆脏数据,那你这就是不合格的测试工具啊
    cweijan
        4
    cweijan  
    OP
       2020-06-01 15:15:36 +08:00
    @gengz 我们公司现在是有用 yapi 搭建文档, 存在以下问题:
    1. 无法快速定位到接口进行调用
    2. 创建测试用例组太麻烦, 比如我要保存用户后立刻测试更新用户
    3. 对接口结果进行断言验证
    你可以试下, 很方便的
    zhazi
        5
    zhazi  
       2020-06-01 15:15:50 +08:00 via Android
    如果在服务已经启动的情况下 mockmvc 就可以提供 api 访问了,不需要对 spring 容器初始化
    cweijan
        6
    cweijan  
    OP
       2020-06-01 15:16:13 +08:00
    @zhazi 就是给后端人员进行接口自测的
    cweijan
        7
    cweijan  
    OP
       2020-06-01 15:17:44 +08:00
    @zhazi mockmvc 我也是有看过, 构建太麻烦, 写这个主要是为了减少学习成本并能够快速进行接口自测
    chendy
        8
    chendy  
       2020-06-01 15:19:18 +08:00
    因为要拉应用起来,然后跑测试去调用,所以已经不是单元测试而是集成测试了…
    当然如果 lz 是针对自己的使用场景开发的工具,那也是极好的,就是不一定适合别人了
    cweijan
        9
    cweijan  
    OP
       2020-06-01 15:30:00 +08:00
    @chendy 确实属于集成测试, 主要是没有更好的接口自测方案, 都是人肉调用 http, 而这个可以让后端人员直接面向 controller 进行测试
    efaun
        10
    efaun  
       2020-06-01 16:17:33 +08:00
    JB 有个插件更方便,RestfulToolkit
    hantsy
        11
    hantsy  
       2020-06-01 17:03:10 +08:00   ❤️ 2
    一年到头,难得 V 站上有人讨论测试。

    Spring Boot 默认 test-starter 除了自己提供对 JUnit 等集成外,还包括大量第三方测试工具。
    用于 REST APIs 的 包括 MockMVc,TestRestTemplate,WebTestClient,这个 starter 加入流行的测试工具的 Dep,Mockito, AssertJ,JSONPath 等,另外自己可以添加 RestAssured 提供 REST APIs 的 BDD 测试体验。

    对于环境依赖,Spring 提供一系列 @AutoConfigure/@DataJpaTest 等测试 Slices 等,不必加载个 Context 。对于外部数据库等依赖,现在 TestContainers 是不错的选择,将来 Spring Boot 会它代替 embedded mongo 等。

    对于服务与之间测试,Spring WebMvc 提供了 MockServer ( Mock 远程服务),另外 Spring Cloud Contract 提供了 CDC 模式测试。

    不得不说 Spring Security 5 在测试 OAuth2,Oidc 很大的改进,现在 resource server 可以在 Mock 环境下测试。

    @cweijan 如果说速度,集成环境加载的资源太多, 什么方法快不了(跑整个集成测试的任务,应该在 CI 上进行)。只有 Mock 环境可以加快测试运行速度。

    集成测试: https://github.com/hantsy/spring-reactive-jwt-sample/blob/master/src/test/java/com/example/demo/IntegrationTests.java

    单独测试 Controller ( Mock 环境): https://github.com/hantsy/spring-reactive-jwt-sample/blob/master/src/test/java/com/example/demo/PostControllerTest.java

    从你的代码片断,我没看出来你这个项目有多少实用性。当然任何创作值得鼓励。
    hantsy
        12
    hantsy  
       2020-06-01 17:07:51 +08:00
    https://github.com/hantsy/spring-microservice-sample/tree/master/post-service/src/test/java/com/hantsylabs/sample/springmicroservice/post 提供了传统 Spring WebMvc 的测试,包括大部分 Spring Boot 提供的测试工具。
    hantsy
        13
    hantsy  
       2020-06-01 17:18:13 +08:00
    你这个项目 https://github.com/cweijan/http-test 的测试代码呢?没有提交?
    cweijan
        14
    cweijan  
    OP
       2020-06-01 17:26:18 +08:00
    @hantsy 看来你对测试研究的很深, 佩服, 我的目的很简单, 想要快速测试我写的 controller, 我使用 @SpringBootTest 之后, 启动太久, 没法快速测试我的接口, 而公司也没有要求要写测试用例, 测试用例仅仅是用来自测的, 这个库其实就是个 http client, 用来替换 postman 和 yapi.
    cweijan
        15
    cweijan  
    OP
       2020-06-01 17:27:14 +08:00
    @hantsy 测试代码我没有提交, 你有兴趣的话在本地试下.
    cweijan
        16
    cweijan  
    OP
       2020-06-01 17:28:14 +08:00
    @hantsy 其实重点就在于快
    hantsy
        17
    hantsy  
       2020-06-01 20:48:11 +08:00
    @cweijan 你这个只是 Client View 来测试,仅仅测试功能而已。从测试金字塔来看,在最顶端。没有大量的基础单元测试,代码质量同样很脆弱。

    https://martinfowler.com/bliki/TestPyramid.html
    CoderGeek
        18
    CoderGeek  
       2020-06-01 20:52:53 +08:00
    从体来说 内部测试与 postman 这种还是不大一样 本身 postman 这种也有扩展工具
    JarvisRay
        19
    JarvisRay  
       2020-06-02 16:15:52 +08:00
    还是 postman 吧,swagger 也集成了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1343 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 17:47 · PVG 01:47 · LAX 09:47 · JFK 12:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.