sqlite - Golang:即使在 db.Close() 上,集成测试也会命中同一个数据库实例
问题描述
我有一个测试套件,它使用内存中的 sqlite 实例来运行数据库查询。添加一些测试后,我突然开始在尝试执行插入的每一行中遇到大量“UNIQUE 约束失败...”错误。这使得我的所有测试看起来都在连接、写入和读取同一个数据库实例。这是测试数据库实例的生成方式
const DBProvider = "sqlite3"
// DBConnection is the connection string to use for testing
const DBConnection = "file::memory:?cache=shared"
// NewMigratedDB returns a new connection to a migrated database
func NewMigratedDB(provider string, connection string, models ...interface{}) (*gorm.DB, error) {
db, err := gorm.Open(provider, connection)
if err != nil {
return nil, err
}
db = db.AutoMigrate(models...)
if db.Error != nil {
return nil, err
}
return db, nil
}
以下是它在测试中的使用方式 -
db, err := test.NewMigratedDB(test.DBProvider, test.DBConnection, models...)
defer db.Close()
// read/write anything
如何对 NewMigratedDB 进行每次调用以生成不同的 SQLite 实例,该实例仅侦听来自实例化它的单元测试的查询
解决方案
首先,查看您NewMigratedDB
在测试中如何使用的完整示例会很有帮助。这是我根据我能看到的(和我看不到的)提出的建议。
设置命名内存数据库
您的每个单元测试似乎都使用 SQLite 数据库的相同内存副本。使用以下语法创建内存数据库的单独命名实例。如果您的测试并行运行,它们很可能共享同一个数据库。替换test1
为每个并行运行的测试的唯一名称(有关更多信息,请参阅sqlite 文档)。
如果在单个进程中需要两个或多个不同但可共享的内存数据库,则
mode=memory
查询参数可以与 URI 文件名一起使用以创建命名的内存数据库
const DBConnection = "file:test1?mode=memory&cache=shared"
在测试之间打开和关闭
您还需要确保每次测试都初始化一个新的数据库,而不是在测试功能的顶部一次。例如:
func TestSomething(t *testing.T) {
// Don't initialize it here
t.Run("test1", func(t *testing.T) {
db, err := test.NewMigratedDB(test.DBProvider, test.DBConnection, models...)
defer db.Close()
// Do something
})
t.Run("test2", func(t *testing.T) {
db, err := test.NewMigratedDB(test.DBProvider, test.DBConnection, models...)
defer db.Close()
// Do something
})
}
如果您在每次测试之前和之后打开和关闭,并且您没有任何同时运行的测试也连接到 sqlite,那么关闭连接应该清除 sqlite 数据库,并且您不需要使用命名的内存数据库作为下一次调用gorm.Open
. 那里有很多“如果”,所以选择你的毒药。
推荐阅读
- python - 为什么使用列标题名称很好但不能使用列索引
- wpf - 动态检查 DataGrid 中单元格的验证状态
- .net - 我可以在 IIS 中托管 Worker Service 项目吗?
- angular - Nx 工作空间:将样式文件从库导入到应用程序
- c# - 在所有 Azure 函数调用中强制执行区域性不起作用
- python-3.x - cv2.findTransformECC 如何忽略小颗粒
- python - Python程序在尝试成功后退出:块
- oracle - 在 LOOP 中显示 EXECUTE IMMEDIATE 语句的输出
- java - 在java中并行运行固定数量的线程
- udp - Gstreamer 无法播放来自其他电脑的流:h264->rtp->udp