spring boot mybatisplus集成_spring-boot系列之集成测试

v2-c61a0a0ec7219d9a7c0a332067c74af5_1440w.jpg?source=172ae18b

如果希望很方便针对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时的一些配置,上述代码是用了随机端口,当然也可以预定义端口,像这样

1
@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")
@Test
public 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增加一个stepgradle 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内置的测试服务可以很快速的验证API,我现在都不用把服务启动再通过人工页面点击来测试自己的API,直接与前端同事沟通好Request的格式,写个Case就可以验证。

当然这种方式也有一个不足就是不方便对系统进行压力测试,之前在公司的API测试用例都是Jmeter写的,做性能测试的时候会方便很多。

仍在寻找合适的跑性能的工具,如有推荐欢迎留言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值