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

2020-06-01 14:52:05 +08:00
 cweijan

做 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 容器, 耗时实在太久, 该方式毫秒级即可运行完测试.

3999 次点击
所在节点    Java
19 条回复
zoharSoul
2020-06-01 15:09:04 +08:00
感觉挺有意思的...
gengz
2020-06-01 15:11:10 +08:00
我选择 swagger
zhazi
2020-06-01 15:13:00 +08:00
这东西需要启动项目,就是个 httpclient,完全没达到测试的目的,不能保证可重复性,测试完数据库一堆脏数据,那你这就是不合格的测试工具啊
cweijan
2020-06-01 15:15:36 +08:00
@gengz 我们公司现在是有用 yapi 搭建文档, 存在以下问题:
1. 无法快速定位到接口进行调用
2. 创建测试用例组太麻烦, 比如我要保存用户后立刻测试更新用户
3. 对接口结果进行断言验证
你可以试下, 很方便的
zhazi
2020-06-01 15:15:50 +08:00
如果在服务已经启动的情况下 mockmvc 就可以提供 api 访问了,不需要对 spring 容器初始化
cweijan
2020-06-01 15:16:13 +08:00
@zhazi 就是给后端人员进行接口自测的
cweijan
2020-06-01 15:17:44 +08:00
@zhazi mockmvc 我也是有看过, 构建太麻烦, 写这个主要是为了减少学习成本并能够快速进行接口自测
chendy
2020-06-01 15:19:18 +08:00
因为要拉应用起来,然后跑测试去调用,所以已经不是单元测试而是集成测试了…
当然如果 lz 是针对自己的使用场景开发的工具,那也是极好的,就是不一定适合别人了
cweijan
2020-06-01 15:30:00 +08:00
@chendy 确实属于集成测试, 主要是没有更好的接口自测方案, 都是人肉调用 http, 而这个可以让后端人员直接面向 controller 进行测试
efaun
2020-06-01 16:17:33 +08:00
JB 有个插件更方便,RestfulToolkit
hantsy
2020-06-01 17:03:10 +08:00
一年到头,难得 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
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
2020-06-01 17:18:13 +08:00
你这个项目 https://github.com/cweijan/http-test 的测试代码呢?没有提交?
cweijan
2020-06-01 17:26:18 +08:00
@hantsy 看来你对测试研究的很深, 佩服, 我的目的很简单, 想要快速测试我写的 controller, 我使用 @SpringBootTest 之后, 启动太久, 没法快速测试我的接口, 而公司也没有要求要写测试用例, 测试用例仅仅是用来自测的, 这个库其实就是个 http client, 用来替换 postman 和 yapi.
cweijan
2020-06-01 17:27:14 +08:00
@hantsy 测试代码我没有提交, 你有兴趣的话在本地试下.
cweijan
2020-06-01 17:28:14 +08:00
@hantsy 其实重点就在于快
hantsy
2020-06-01 20:48:11 +08:00
@cweijan 你这个只是 Client View 来测试,仅仅测试功能而已。从测试金字塔来看,在最顶端。没有大量的基础单元测试,代码质量同样很脆弱。

https://martinfowler.com/bliki/TestPyramid.html
CoderGeek
2020-06-01 20:52:53 +08:00
从体来说 内部测试与 postman 这种还是不大一样 本身 postman 这种也有扩展工具
JarvisRay
2020-06-02 16:15:52 +08:00
还是 postman 吧,swagger 也集成了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/677494

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX