golang基于单事务的数据库驱动测试插件go-txdb的使用

golang基于单事务的数据库驱动测试插件go-txdb的使用

概述

go-txdb是一个基于单事务的数据库sql驱动。当连接打开时,它会启动一个事务,所有在该sql.DB上执行的操作都将在这个事务内进行。如果执行并发操作,会获取锁并始终释放连接,语句和行不会持有连接。

Build Status GoDoc

为什么有用

一个非常基本的用例是,如果你想进行功能测试,你可以准备一个测试数据库,在每个测试中你不需要重新加载数据库。所有测试都在事务内隔离,因此执行速度快。你不需要在代码中接口化你的sql.DB引用,txdb就像一个标准的sql.Driver。

使用示例

基本使用方式

package main

import (
    "database/sql"
    "log"

    "github.com/DATA-DOG/go-txdb"
    _ "github.com/go-sql-driver/mysql"
)

func init() {
    // 注册一个名为"txdb"的sql驱动
    txdb.Register("txdb", "mysql", "root@/txdb_test")
}

func main() {
    // dsn作为连接池的唯一标识符
    db, err := sql.Open("txdb", "identifier")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    if _, err := db.Exec(`INSERT INTO users(username) VALUES("gopher")`); err != nil {
        log.Fatal(err)
    }
}

使用sql.OpenDB方式(Go 1.10+)

package main

import (
    "database/sql"
    "log"

    "github.com/DATA-DOG/go-txdb"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    db := sql.OpenDB(txdb.New("mysql", "root@/txdb_test"))
    defer db.Close()

    if _, err := db.Exec(`INSERT INTO users(username) VALUES("gopher")`); err != nil {
        log.Fatal(err)
    }
}

每次运行此应用程序时,它都将保持与之前相同的状态。

测试

使用主要用于测试目的。测试需要数据库访问,支持使用postgres和mysql数据库。最简单的方法是使用testcontainers,通过将相应的数据库DSN值设置为AUTO来启用。例如:

MYSQL_DSN=AUTO PSQL_DSN=AUTO go test ./...

如果希望使用正在运行的本地数据库实例,也可以直接提供DSN:

MYSQL_DSN=root:pass@/ PSQL_DSN=postgres://postgres:pass@localhost/ go test ./...

要仅针对MySQL或PostgreSQL运行测试,可以仅提供相应的DSN值;任何未设置的DSN都将跳过测试。

文档

请参阅godoc获取一般API详细信息。请参阅.travis.yml获取支持的go版本。

贡献

欢迎提交pull request。请注意,如果你希望贡献对公共API(导出的方法或类型)的扩展,请在提交前先开一个issue讨论这些更改是否可以被接受。所有向后不兼容的更改都将被谨慎对待。

公共API已经锁定,因为它是一个sql.Driver,不会改变。

许可证

txdb根据三条款BSD许可证授权


更多关于golang基于单事务的数据库驱动测试插件go-txdb的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang基于单事务的数据库驱动测试插件go-txdb的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go-Txdb: 基于单事务的数据库驱动测试插件

go-txdb 是一个用于 Go 语言数据库测试的优秀工具,它允许你在测试中使用真实数据库事务,而不会污染你的测试数据库。下面我将详细介绍它的使用方法和示例代码。

什么是 go-txdb

go-txdb 是一个实现了 database/sql 驱动接口的库,专门为测试设计。它的核心特点是:

  1. 每个测试用例都在独立的事务中运行
  2. 测试结束后自动回滚事务,保持数据库干净
  3. 支持多种数据库后端(MySQL, PostgreSQL, SQLite 等)

安装

go get github.com/DATA-DOG/go-txdb

基本使用示例

package main_test

import (
	"database/sql"
	"testing"

	"github.com/DATA-DOG/go-txdb"
	_ "github.com/go-sql-driver/mysql"
)

func init() {
	// 注册 txdb 驱动,使用 "txdb" 作为驱动名
	// 这里我们使用 MySQL 作为后端数据库
	txdb.Register("txdb", "mysql", "user:password@/dbname")
}

func TestUserCRUD(t *testing.T) {
	// 每个测试用例获取一个唯一的连接名
	db, err := sql.Open("txdb", "identifier")
	if err != nil {
		t.Fatalf("failed to open db: %v", err)
	}
	defer db.Close()

	// 测试代码在这里运行,所有操作都在事务中
	// 例如插入测试数据
	_, err = db.Exec("INSERT INTO users(name, email) VALUES(?, ?)", "test", "test@example.com")
	if err != nil {
		t.Fatalf("failed to insert user: %v", err)
	}

	// 验证数据
	var count int
	err = db.QueryRow("SELECT COUNT(*) FROM users WHERE name = ?", "test").Scan(&count)
	if err != nil {
		t.Fatalf("failed to query users: %v", err)
	}
	if count != 1 {
		t.Errorf("expected 1 user, got %d", count)
	}

	// 测试结束时,事务会自动回滚
}

高级用法

1. 使用自定义连接池设置

func init() {
	txdb.Register("txdb", "mysql", "user:password@/dbname?parseTime=true")
}

func TestWithConnectionPool(t *testing.T) {
	db, err := sql.Open("txdb", "pool_test")
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	// 设置连接池参数
	db.SetMaxOpenConns(10)
	db.SetMaxIdleConns(5)
	db.SetConnMaxLifetime(time.Hour)

	// 测试代码...
}

2. 使用多个数据库

func init() {
	txdb.Register("txdb_mysql", "mysql", "user:password@/dbname")
	txdb.Register("txdb_postgres", "postgres", "user=postgres password=secret dbname=test sslmode=disable")
}

func TestMultiDatabase(t *testing.T) {
	mysqlDB, err := sql.Open("txdb_mysql", "mysql_test")
	if err != nil {
		t.Fatal(err)
	}
	defer mysqlDB.Close()

	pgDB, err := sql.Open("txdb_postgres", "pg_test")
	if err != nil {
		t.Fatal(err)
	}
	defer pgDB.Close()

	// 在两个数据库中执行测试...
}

3. 使用测试套件

func TestMain(m *testing.M) {
	// 初始化 txdb
	txdb.Register("txdb", "mysql", "user:password@/dbname")

	// 运行测试
	code := m.Run()

	// 清理工作
	os.Exit(code)
}

func TestSuite(t *testing.T) {
	// 测试用例1
	t.Run("CreateUser", func(t *testing.T) {
		db, err := sql.Open("txdb", t.Name())
		if err != nil {
			t.Fatal(err)
		}
		defer db.Close()
		
		// 测试代码...
	})

	// 测试用例2
	t.Run("DeleteUser", func(t *testing.T) {
		db, err := sql.Open("txdb", t.Name())
		if err != nil {
			t.Fatal(err)
		}
		defer db.Close()
		
		// 测试代码...
	})
}

最佳实践

  1. 为每个测试用例使用唯一标识符:可以使用 t.Name() 作为连接标识符,确保每个测试用例获得独立的事务。

  2. 避免并行测试:由于 go-txdb 使用全局注册表,并行测试可能导致问题。如果需要并行测试,考虑使用不同的驱动名称。

  3. 初始化测试数据:可以在测试前使用 db.Exec() 插入必要的测试数据,这些数据会在测试结束后自动回滚。

  4. 清理资源:虽然事务会自动回滚,但仍需记得关闭数据库连接。

  5. 结合测试框架:可以与 testify/suite 等测试框架结合使用,创建更结构化的测试。

限制

  1. 不支持测试中的嵌套事务
  2. 并行测试需要额外处理
  3. 某些数据库特定的功能可能无法完全模拟

go-txdb 是一个强大的测试工具,它让你可以在测试中使用真实的数据库操作,同时保持测试环境的干净。通过自动事务管理,你可以专注于测试逻辑,而不必担心测试数据的清理工作。

回到顶部