欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java Testcontainers库实现测试功能

程序员文章站 2022-03-23 22:02:56
1.testcontainers介绍:testcontainers是一个java库,它支持junit测试,提供公共数据库、seleniumweb浏览器或任何可以在docker容器中运行的轻量级、一次性...

1.testcontainers介绍:

testcontainers是一个java库,它支持junit测试,提供公共数据库、seleniumweb浏览器或任何可以在docker容器中运行的轻量级、一次性实例。

测试容器使以下类型的测试更加容易:

数据访问层集成测试:

使用mysql,postgresql或oracle数据库的容器化实例测试您的数据访问层代码,但无需在开发人员的计算机上进行复杂的设置,并且测试将始终从已知的数据库状态开始,避免“垃圾”数据的干扰。也可以使用任何其他可以容器化的数据库类型。

应用程序集成测试:

用于在具有相关性(例如数据库,消息队列或web服务器)的短期测试模式下运行应用程序。

ui /验收测试:

使用与selenium兼容的容器化web浏览器进行自动化ui测试。每个测试都可以获取浏览器的新实例,而无需担心浏览器状态,插件版本或浏览器自动升级。您将获得每个测试会话或测试失败的视频记录。

更多:

可以签出各种贡献的模块,或使用 genericcontainer作为基础创建自己的自定义容器类。

2.testcontainers实践示例:

testcontainers提供了多种现成的与测试关联的应用程序容器,如下图:

Java Testcontainers库实现测试功能

在本文中,将演示集成postgresql容器和mockserver容器的测试。

testcontainers必要条件:

1.docker

2.支持的jvm测试框架:junit4,junit5,spock...

2.1 集成postgresql测试依赖:

<dependency>
  <groupid>org.testcontainers</groupid>
  <artifactid>testcontainers</artifactid>
  <version>1.12.5</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupid>org.testcontainers</groupid>
 	<!--指定数据库名称,mysql,mariadb等等-->
  <artifactid>postgresql</artifactid>
  <version>1.12.5</version>
  <scope>test</scope>
</dependency>

配置:

在项目的src/test/resources/application.properties文件中配置postgresql相关信息

#将驱动程序设置为org.testcontainers.jdbc.containerdatabasedriver,它是一个testcontainers jdbc代理驱动程序。初始化数据源时,此驱动程序将负责启动所需的docker容器。
spring.datasource.driver-class-name=org.testcontainers.jdbc.containerdatabasedriver

#将jdbc url设置为jdbc:tc:<database image>:<version>:///以便testcontainers知道要使用哪个数据库。
#tc_initscript=指定的数据库初始化的脚本文件位置
spring.datasource.url=jdbc:tc:postgresql:9.6:///?tc_initscript=file:src/main/resources/init_db.sql

#将方言明确设置为数据库的方言实现,否则在启动应用程序时会收到异常。当您在应用程序中使用jpa时(通过spring data jpa),此步骤是必需的
spring.jpa.database-platform=org.hibernate.dialect.postgresql9dialect

测试示例:

为了在@datajpatest中使用tc,您需要确保使用了应用程序定义的(自动配置的)数据源。您可以通过使用@autoconfiguretestdatabase注释测试来轻松完成此操作,如下所示:

@runwith(springjunit4classrunner.class)
@datajpatest
@autoconfiguretestdatabase(replace = autoconfiguretestdatabase.replace.none)
public class ownerrepositorytests {

  @autowired
  private ownerrepository ownerrepository;

  @test
  void findallreturnsjohndoe() { // as defined in tc-initscript.sql
    var owners = ownerrepository.findall();
    assertthat(owners.size()).isone();
    assertthat(owners.get(0).getfirstname()).isequalto("john");
    assertthat(owners.get(0).getlastname()).isequalto("doe");
  }
}

以上测试将使用testcontainers提供的postgresql容器进行测试,从而排除了外部环境对测试的干扰。

当需要用本地数据库进行集成测试时,我们只要使用@springboottest替换如上两个注解即可:

@springboottest(webenvironment = springboottest.webenvironment.random_port)
@autoconfiguremockmvc
public class ownerresourcetests {

  @autowired
  webapplicationcontext wac;

  @test
  void findallreturnsjohndoe() throws exception {
    given()
        .webappcontextsetup(wac)
    .when()
        .get("/owners")
    .then()
        .status(httpstatus.ok)
        .body(
            "_embedded.owners.firstname", containsinanyorder("john"),
            "_embedded.owners.lastname", containsinanyorder("doe")
        );
  }
}

以上测试将使用真实运行环境的数据库进行测试。

2.2 集成mockserver测试

mock server可用于通过将请求与用户定义的期望进行匹配来模拟http服务。

依赖:

	<dependency>
      <groupid>org.testcontainers</groupid>
      <artifactid>mockserver</artifactid>
      <version>1.12.5</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupid>org.mock-server</groupid>
      <artifactid>mockserver-netty</artifactid>
      <version>5.5.4</version>
    </dependency>
    <dependency>
      <groupid>org.mock-server</groupid>
      <artifactid>mockserver-client-java</artifactid>
      <version>5.5.4</version>
    </dependency>

测试示例:

//创建一个mockserver容器
@rule
public mockservercontainer mockserver = new mockservercontainer();

以及使用java mockserverclient设置简单的期望。

new mockserverclient(mockserver.getcontaineripaddress(), mockserver.getserverport())
        .when(request()
            .withpath("/person")
            .withquerystringparameter("name", "peter"))
        .respond(response()
            .withbody("peter the person!"));
//...当一个get请求至'/person?name=peter' 时会返回 "peter the person!"

测试(使用restassured进行测试):

restassured.baseuri = "http://" + mockserver.getcontaineripaddress();
restassured.port = mockserver.getserverport();
given().queryparam("name", "peter")
        .get("/person")
        .then()
        .statuscode(httpstatus.ok.value())
        .body(is("peter the person!"));

完整代码如下:

@runwith(springjunit4classrunner.class)
public class onetests {
  @rule
  public mockservercontainer mockserver = new mockservercontainer();

  @test
  public void v() {
    restassured.baseuri = "http://" + mockserver.getcontaineripaddress();
    restassured.port = mockserver.getserverport();

    new mockserverclient(mockserver.getcontaineripaddress(), mockserver.getserverport())
        .when(request()
            .withpath("/person")
            .withquerystringparameter("name", "peter"))
        .respond(response()
            .withbody("peter the person!"));

    given().queryparam("name", "peter")
        .get("/person")
        .then()
        .statuscode(httpstatus.ok.value())
        .body(is("peter the person!"));
  }
}

3.总结:

testcontainers轻松的解决了集成测试时测试代码与本地组件耦合,从而出现各种意外失败的问题(比如本地数据库中存在脏数据影响到了集成测试,多个集成测试同时运行时相互干扰导致测试结果意外失败)。笔者之前专门为集成测试准备了一套数据库,使数据和其他环境隔离掉,但还是会遇到多个集成测试一起跑相互干扰的问题,testcontainers轻松的解决了笔者的问题。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。