sqlmock 是一个实现 sql/driver 的mock库。它不需要建立真正的数据库连接就可以在测试中模拟任何 sql 驱动程序的行为。使用它可以很方便的在编写单元测试的时候mock sql语句的执行结果。
安装mockgen
go get github.com/DATA-DOG/go-sqlmock
针对测试的数据库操作函数编写单元测试(本例为向数据库表插入数据)
数据库操作函数employees.go
func (repo *EmployeesRepository) CreateEmployee(employee *domain.Employees) (err error) {
err = repo.db.Debug().Create(&employee).Error
if err != nil {
err = fmt.Errorf("[repository.r.CreateEmployee] failed: employee = %+v, error = %w ", employee, err)
return
}
return
}
domain.Employees 数据结构
package domain
import(
"time"
)
type Employees struct{
ID int `json:"id" gorm:"primary_key"`
Code string `json:"code"`
Name string `json:"name"`
DepartmentID int `json:"departmentid"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
针对测试的数据库操作函数编写单元测试employees_test.go
package impl
import (
"testing"
"github.com/DATA-DOG/go-sqlmock"
"github.com/magiconair/properties/assert"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"server/domain"
)
func getDBMock() (*gorm.DB, sqlmock.Sqlmock, error) {
// mock一个*sql.DB对象,不需要连接真实的数据库
db, mock, err := sqlmock.New()
if err != nil {
return nil, nil, err
}
//测试时不需要真正连接数据库
gdb, err := gorm.Open(postgres.New(postgres.Config{
DriverName: "postgres",
PreferSimpleProtocol: true,
Conn: db,
}), &gorm.Config{})
if err != nil {
return nil, nil, err
}
return gdb, mock, nil
}
func TestEmployeesRepository_CreateEmployees(t *testing.T) {
type fields struct {
db *gorm.DB
}
type args struct {
employees *domain.Employees
}
db, mock, err := getDBMock()
assert.Equal(t, err, nil)
tests := []struct {
name string
fields fields
args args
invoke func(args)
wantErr bool
}{
{
name: "create Employees successful",
fields: fields{
db: db,
},
args: args{employees: &domain.Employees{
ID:0,
Code: "1",
Name:"zhangsan",
DepartmentID:1,
}},
invoke: func(args args) {
mock.ExpectQuery("INSERT INTO (.+)").WithArgs(
args.employees.Code, args.employees.Name,args.employees.DepartmentID,sqlmock.AnyArg(),sqlmock.AnyArg(),sqlmock.AnyArg()).
WillReturnRows(sqlmock.NewRows([]string{"ID"}).AddRow(1))
},
},
{
name: "create Employees failed",
fields: fields{
db: db,
},
args: args{employees: &domain.Employees{
Code: "1",
Name:"zhangsan",
DepartmentID:2,
}},
invoke: func(args args) {
mock.ExpectQuery("INSERT INTO (.+)").WithArgs(
args.employees.Code,args.employees.Name,args.employees.DepartmentID,sqlmock.AnyArg(),sqlmock.AnyArg(),sqlmock.AnyArg()).
WillReturnError(gorm.ErrInvalidData)
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &EmployeesRepository{
db: tt.fields.db,
}
tt.invoke(tt.args)
if err := c.CreateEmployee(tt.args.employees); (err != nil) != tt.wantErr {
t.Errorf("CreateEmployees() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
在测试文件所在目录下,执行go test -v
执行结果
21:46:24.176',NULL) RETURNING "id"
--- PASS: TestEmployeesRepository_CreateEmployees (0.00s)
--- PASS: TestEmployeesRepository_CreateEmployees/create_Employees_successful (0.00s)
--- PASS: TestEmployeesRepository_CreateEmployees/create_Employees_failed (0.00s)
PASS
ok server/repository/impl 0.008s
所有博客均为自己学习的笔记。如有错误敬请理解。
分类:
go语言
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了