千家信息网

spring boot之集成测试的示例分析

发表于:2025-11-07 作者:千家信息网编辑
千家信息网最后更新 2025年11月07日,这篇文章将为大家详细讲解有关spring boot之集成测试的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。如果希望很方便针对API进行测试,并且方便的集成
千家信息网最后更新 2025年11月07日spring boot之集成测试的示例分析

这篇文章将为大家详细讲解有关spring boot之集成测试的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

如果希望很方便针对API进行测试,并且方便的集成到CI中验证每次的提交,那么spring boot自带的IT绝对是不二选择。

迅速编写一个测试Case

@RunWith(SpringRunner.class)@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)@ActiveProfiles({Profiles.ENV_IT})public class DemoIntegrationTest{  @Autowired  private FooService fooService;  @Test  public void test(){    System.out.println("tested");  }}

其中 SpringBootTest 定义了跑IT时的一些配置,上述代码是用了随机端口,当然也可以预定义端口,像这样

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, properties = {"server.port=9990"})

ActiveProfiles 强制使用了IT的Profile,从最佳实践上来说IT Profile所配置的数据库或者其他资源组件的地址,应该是与开发或者Staging环境隔离的。因为当一个IT跑完之后很多情况下我们需要清除测试数据。

你能够发现这样的Case可以使用 Autowired 注入任何想要的Service。这是因为spring将整个上下文都加载了起来,与实际运行的环境是一样的,包含了数据库,缓存等等组件。如果觉得测试时不需要全部的资源,那么在profile删除对应的配置就可以了。这就是一个完整的运行环境,唯一的区别是当用例跑完会自动shutdown。

测试一个Rest API

强烈推荐一个库,加入到gradle中

testCompile 'io.rest-assured:rest-assured:3.0.3'

支持JsonPath,十分好用,具体文档戳 这里

@Sql(scripts = "/testdata/users.sql")@Testpublic void test001Login() {  String username = "demo@demo.com";  String password = "demo";  JwtAuthenticationRequest request = new JwtAuthenticationRequest(username, password);  Response response = given().contentType(ContentType.JSON).body(request)      .when().post("/auth/login").then()      .statusCode(HttpStatus.OK.value())      .extract()      .response();  assertThat(response.path("token"), is(IsNull.notNullValue()));  assertThat(response.path("expiration"), is(IsNull.notNullValue()));}

@Sql 用于在测试前执行sql插入测试数据。注意 given().body() 中传入的是一个java对象 JwtAuthenticationRequest ,因为rest-assured会自动帮你用 jackson 将对象序列化成json字符串。当然也可以将转换好的json放到body,效果是一样的。

返回结果被一个Response接住,之后就可以用JsonPath获取其中数据进行验证。当然还有一种更直观的办法,可以通过 response.asString() 获取完整的response,再反序列化成java对象进行验证。

至此,最基本的IT就完成了。 在Jenkins增加一个step gradle test 就可以实现每次提交代码都进行一次测试。

一些复杂的情况

数据混杂

这是最容易发生,一个项目有很多dev,每个dev都会写自己的IT case,那么如果数据之间产生了影响怎么办。很容易理解,比如一个测试批量写的场景,最后验证方式是看写的数据量是不是10w行。那么另外一个dev写了其他的case恰好也新增了一条数据到这张表,结果变成了10w+1行,那么批量写的case就跑不过了。

为了杜绝这种情况,我们采用每次跑完一个测试Class就将数据清空。既然是基于类的操作,可以写一个基类解决。

@RunWith(SpringRunner.class)@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)@ActiveProfiles({Profiles.ENV_IT})public abstract class BaseIntegrationTest {  private static JdbcTemplate jdbcTemplate;  @Autowired  public void setDataSource(DataSource dataSource) {    jdbcTemplate = new JdbcTemplate(dataSource);  }  @Value("${local.server.port}")  protected int port;  @Before  public void setupEnv() {    RestAssured.port = port;    RestAssured.basePath = "/api";    RestAssured.baseURI = "http://localhost";    RestAssured.config = RestAssured.config().httpClient(HttpClientConfig.httpClientConfig().httpMultipartMode(HttpMultipartMode.BROWSER_COMPATIBLE));  }  public void tearDownEnv() {    given().contentType(ContentType.JSON)        .when().post("/auth/logout");  }  @AfterClass  public static void cleanDB() throws SQLException {    Resource resource = new ClassPathResource("/testdata/CleanDB.sql");    Connection connection = jdbcTemplate.getDataSource().getConnection();    ScriptUtils.executeSqlScript(connection, resource);    connection.close();  }}

@AfterClass 中使用了jdbcTemplate执行了一个CleanDB.sql,通过这种方式清除所有测试数据。

@Value("${local.server.port}") 也要提一下,因为端口是随机的,那么Rest-Assured不知道请求要发到losthost的哪个端口上,这里使用 @Value 获取当前的端口号并设置到 RestAssured.port 就解决了这个问题。

共有数据怎么处理

跑一次完整的IT,可能需要经历数十个Class,数百个method,那么如果一些数据是所有case都需要的,只有在所有case都跑完才需要清除怎么办?换句话说,这种数据清理不是基于 类 的,而是基于一次 运行 。比如初始用户数据,城市库等等

我们耍了个小聪明,借助了 flyway

@Configuration@ConditionalOnClass({DataSource.class})public class UpgradeAutoConfiguration {  public static final String FLYWAY = "flyway";  @Bean(name = FLYWAY)  @Profile({ENV_IT})  public UpgradeService cleanAndUpgradeService(DataSource dataSource) {    UpgradeService upgradeService = new FlywayUpgradeService(dataSource);    try {      upgradeService.cleanAndUpgrade();    } catch (Exception ex) {      LOGGER.error("Flyway failed!", ex);    }    return upgradeService;  }}

可以看到当Profile是IT的情况下, flyway 会drop掉所有表并重新依次执行每次的upgrade脚本,由此创建完整的数据表,当然都是空的。在项目的test路径下,增加一个版本极大的sql,这样就可以让 flyway 在最后插入共用的测试数据,例如 src/test/resources/db/migration/V999.0.1__Insert_Users.sql ,完美的解决各种数据问题。

关于"spring boot之集成测试的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

数据 测试 情况 端口 验证 对象 环境 篇文章 运行 配置 示例 分析 代码 序列 怎么办 数据库 方式 更多 组件 结果 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 深圳市智仁软件开发 电商小程序软件开发价钱 工业网络安全防控 如何用华为下载魅族服务器游戏 添加表里信息的数据库语句 把笔记本电脑做服务器可以不 金蝶迷你版打开数据库 独立于任何数据库管理系统的 二维码数据库字段 高新网络技术图片 医院网络安全方案范本 服务器外挂 软件开发使用的框架 深圳蓝思网络技术有限公司 软件开发与应用是学什么的 数据库查询类笔试题 软件开发sa什么职位 数据库技术及应用微课 北京光蓝网络技术有限公司 朔州网络技术哪家强 软件开发用户手册范文 网络技术进行英语课堂 数据库连接怎么不让数据重复 网络安全法中关于防DOS解读 重载机车网络技术与通信技术 广州交警交费对方服务器断开连接 无限法则怎么找到连接到服务器 山东省浪潮服务器销售地址在哪里 上海银联软件开发 mysql 数据库表数量
0