Wordz – 我们数据库的集成测试

在这一部分,我们将回顾 Wordz 应用程序的集成测试,以便对其有一个直观的了解。我们将在第 14 章《驱动数据库层》和第 15 章《驱动Web层》中详细介绍如何编写这些测试以及如何设置测试工具。

从数据库中获取单词

在我们之前的设计工作中,我们确定了 Wordz 需要一个地方来存储待猜测的候选单词。我们定义了一个名为 WordRepository 的接口,以将我们与存储细节隔离。在那个迭代中,我们只定义了一个接口方法:

public interface WordRepository {
    String fetchWordByNumber(int wordNumber);
}

WordRepository 接口的实现将访问数据库并返回给定 wordNumber 的单词。我们将在第 14 章《驱动数据库层》中实现这一点。现在,让我们先大致看一下集成测试的样子。该测试使用开源库来帮助编写测试并提供数据库。我们选择了以下工具:

以下是测试代码:

package com.wordz.adapters.db;

import com.github.database.rider.core.api.connection.ConnectionHolder;
import com.github.database.rider.core.api.dataset.DataSet;
import com.github.database.rider.junit5.api.DBRider;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.postgresql.ds.PGSimpleDataSource;

import javax.sql.DataSource;
import static org.assertj.core.api.Assertions.assertThat;

@DBRider
public class WordRepositoryPostgresTest {
    private DataSource dataSource;

    @BeforeEach
    void beforeEachTest() {
        var ds = new PGSimpleDataSource();
        ds.setServerNames(new String[]{"localhost"});
        ds.setDatabaseName("wordzdb");
        ds.setUser("ciuser");
        ds.setPassword("cipassword");
        this.dataSource = ds;
    }

    private final ConnectionHolder connectionHolder = () -> dataSource.getConnection();

    @Test
    @DataSet("adapters/data/wordTable.json")
    public void fetchesWord() {
        var adapter = new WordRepositoryPostgres(dataSource);
        String actual = adapter.fetchWordByNumber(27);
        assertThat(actual).isEqualTo("ARISE");
    }
}

fetchesWord() 测试方法由 @DataSet 注解标记。该注解由 database-rider 测试框架提供,它构成了我们测试的 Arrange 步骤。它指定了一个已知的测试数据文件,框架将在测试运行前将其加载到数据库中。数据文件位于 src/test/resources 根文件夹下。注解中的参数给出了其余路径。在我们的例子中,文件将位于 src/test/resources/adapters/data/wordTable.json。其内容如下:

{
  "WORD": [
    {
      "id": 1,
      "number": 27,
      "text": "ARISE"
    }
  ]
}

这个 JSON 文件告诉 database-rider 框架,我们希望将一行数据插入名为 WORD 的数据库表中,列值为 127ARISE

我们暂时不会编写适配器代码来使这个测试通过。我们需要采取几个步骤才能使这个测试编译通过,包括下载各种库并启动 Postgres 数据库。我们将在第 14 章《驱动数据库层》中详细介绍这些步骤。

这段集成测试代码的概述是,它正在测试一个我们将要编写的新类 WordRepositoryPostgres。该类将包含数据库访问代码。我们可以看到明显的 JDBC 对象 javax.sql.DataSource,它代表一个数据库实例。这是我们正在测试与数据库集成的线索。我们可以看到来自数据库测试库的新注解:@DBRider@DataSet。最后,我们可以看到一些熟悉的内容——测试的 ArrangeActAssert 步骤:

  1. Arrange 步骤创建了一个 WordRepositoryPostgres 对象,该对象将包含我们的数据库代码。它与 database-rider 库的 @DataSet 注解一起工作,在测试运行前将一些已知数据放入数据库。

  2. Act 步骤调用 fetchWordByNumber() 方法,传入我们要测试的数字 wordNumber。这个数字与 wordTable.json 文件的内容对齐。

  3. Assert 步骤确认从数据库返回的预期单词是 ARISE

正如我们所看到的,集成测试本质上与单元测试并没有太大区别。