当前位置:   article > 正文

使用groovy+spock优雅的进行单测

使用groovy+spock优雅的进行单测

Groovy是一种基于JVM的动态语言,它可以与Java代码无缝集成。Spock是一个基于Groovy的测试框架,专注于简洁性和可读性。它提供了丰富的测试DSL(领域特定语言),支持行为驱动开发(BDD)风格的测试。

使用Groovy和Spock进行单元测试时,你可以利用Spock的特性编写清晰、易读的测试用例。通过given, when, thenwhere块,你可以清晰地描述测试的前提条件、操作和预期结果。同时,Spock还提供了@Unroll注解,可以让你以数据驱动的方式执行测试用例,从而更全面地覆盖不同的测试场景。

要使用Groovy和Spock进行单元测试,你可以创建一个继承自spock.lang.Specification的测试类,编写测试用例并使用given, when, thenwhere块来描述测试逻辑和数据驱动的测试场景。

1. groovy+spock示例

1.1 简单示例

import spock.lang.Specification

class MathSpec extends Specification {
    
    def "addition test"() {
        given: "two numbers"
        def a = 5
        def b = 3
        
        when: "adding the numbers"
        def result = a + b
        
        then: "the result should be correct"
        result == 8
    }
    
    def "division test"() {
        given: "two numbers"
        def a = 10
        def b = 2
        
        when: "dividing the numbers"
        def result = a / b
        
        then: "the result should be correct"
        result == 5
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

在这个示例中,我们创建了一个MathSpec测试类,其中包含了两个测试用例addition test和division test。每个测试用例都包含了given, when和then块,分别描述了测试的前提条件、操作和预期结果。

你可以在given块中设置测试所需的初始条件,在when块中执行操作,而then块用于验证预期结果。这种清晰的结构使得测试用例易于理解和维护。

如果需要对多组数据执行相同的测试逻辑,可以使用where块和@Unroll注解来进行数据驱动的测试。

1.2 增加where块的示例

import spock.lang.Specification

class MathSpec extends Specification {

    def "multiplication test"(int a, int b, int expected) {
        expect:
        a * b == expected

        where:
        a | b | expected
        2 | 3 | 6
        5 | 5 | 25
        10 | 4 | 40
    }
    
    @Unroll
    def "division test"(int a, int b, int expected) {
        expect:
        a / b == expected

        where:
        a | b | expected
        10 | 2 | 5
        20 | 4 | 5
        30 | 3 | 10
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在这个示例中,我们定义了两个测试用例,分别是multiplication test和division test。每个测试用例都使用where块提供了多组输入数据。@Unroll注解用于展开测试结果,使得每组数据都会生成一个独立的测试用例。

通过这种方式,可以很方便地对多组输入数据执行相同的测试逻辑,并清晰地了解每组数据的测试结果。

1.3 实际应用的示例

在实际开发过程中,验证创建患者信息的不同场景,包含:

  • 创建成功
  • 重复创建
  • 患者信息为空的情形
    在这里插入图片描述

2. 单测相关问题

2.1 与SpringBoot融合

通常创建一个基类,添加@SpringBootTest注解,并继承 spock.lang.Specification 类。

@SpringBootTest
@ContextConfiguration(classes = Application.class)
class BaseTest extends Specification {
	@Autowired
    protected H2Flusher h2Flusher;

    void setup() {
        h2Flusher.flushDB();
    }

    void cleanup() {

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2.2 单测数据与测试数据隔离

通常采用内存数据库进行处理,比如H2,最好使用单独的Profile进行单测。

Springboot下H2数据库的配置

# 数据源配置
spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    url: jdbc:h2:mem:database_name;DB_CLOSE_DELAY=-1;MODE=MYSQL
    username: sa
    password: 
    driver-class-name: org.h2.Driver
    hikari:
      connection-test-query: SELECT 1
      maximum-pool-size: 10
  h2:
    console:
      path: /h2
      enabled: true
      settings:
        trace: true
        web-allow-others: true
  sql:
    init:
      platform: h2
      schema-locations: classpath*:sql/init/schema/schema-{platform}.sql
      data-locations: classpath*:sql/init/data/data-{platform}.sql
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

在H2数据库的URL中,MODE=MYSQL参数的意思是使用MySQL兼容模式。当你在H2数据库的URL中添加MODE=MYSQL参数时,H2数据库会尽可能地模拟MySQL的行为,以便在开发和测试过程中,更好地与MySQL进行集成和迁移。

这意味着你可以使用类似于MySQL的语法和功能,例如特定的SQL语法、函数、存储过程等。这对于在开发阶段使用H2数据库进行测试,并在生产环境中使用MySQL数据库的情况非常有用。

2.3 SQL自动转换(MySQL -> H2)

通常会在用例执行前后进行一些脚本加载和数据清理的工作,基于MySQL的SQL语句在H2环境中可能无法执行,我们又不想维护两套SQL。因此我们可以只提供MySQL的SQL语句,通过提供转换工具实现SQL语句的自动转换。可以使用开源工具,如

mysql2h2-converter

当将基于MySQL的SQL语句转换为H2数据库的SQL语句时,需要注意以下几个主要的差异点:

  • 数据类型差异:

    • MySQL中的DATETIME类型在H2中对应为TIMESTAMP类型。
    • MySQL中的AUTO_INCREMENT在H2中对应为IDENTITY。
    • MySQL中的INT类型在H2中对应为INTEGER类型。
  • SQL语法差异:

    • H2数据库对日期函数的支持可能有所差异,例如日期格式化函数或日期运算函数的语法可能略有不同。
    • 字符串函数的一些用法和语法可能在H2中略有不同,例如字符串拼接函数的语法。
  • 存储过程和触发器:

    • H2数据库的存储过程和触发器支持相对有限,一些复杂的存储过程和触发器可能需要重新设计为触发H2数据库的特定语法和功能。
  • SQL方言:

    • 在一些特定的SQL语句中,例如分页查询、行锁定等,MySQL和H2数据库的语法可能存在差异,需要根据H2数据库的语法规范进行调整。

这些差异点需要在进行数据库迁移时仔细考虑和验证,以确保转换后的SQL语句在H2数据库中能够正确执行。

3. 补充

3.1 pom配置

<properties>
    <spock.version>2.0-M2-groovy-3.0</spock.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.spockframework</groupId>
        <artifactId>spock-core</artifactId>
        <version>${spock.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.spockframework</groupId>
        <artifactId>spock-spring</artifactId>
        <version>${spock.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.github.AlphaHinex.mysql2h2-converter</groupId>
        <artifactId>mysql2h2-converter</artifactId>
        <version>v0.2.2</version>
    </dependency>
</dependencies>

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

3.2 H2Converter使用示例

private static String convertToH2Script(String mysqlScript) throws ParseException {
    Iterator<SqlStatement> sourceIterator = SQLParserManager.parseScript(new StringReader(mysqlScript));
    Iterator<SqlStatement> converted = H2Converter.convertScript(sourceIterator);
    StringBuilder content = new StringBuilder();
    while (converted.hasNext()) {
        content.append(converted.next().toString());
    }
    return content.toString();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

参考

MySQL 脚本转 H2
mysql2h2-converter
how to get mysql2h2-converter v0.3.1

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/760029
推荐阅读
相关标签
  

闽ICP备14008679号