ORM 盛行下,你知道真正执行的 sql 么

推荐理由

在这个 orm 盛行的服务端开发环境下,已经很少有人写 raw sql 了吧,毕竟 orm 框架可以帮助开发人员屏蔽 db 的细节,同时还能在一定成程度上预防 sql 注入的风险,大多数情况下,对业务代码的单测,会使用 sqlite 来 mock 真正的 db,以验证功能的完备性,但当你写完一条 orm 语句后,是否会校验,生成的真正执行的 sql 是你的预期么?是否会校验,在代码变更的时候 sql 语句是否也发生了变更呢?

针对以上两个问题,sqlmock 可以完成对 sql 语句的单侧,让你对 orm 生成的 sql 了如指掌,同时清晰 test raw sql 也让 review 的同事快乐加倍。

实现原理

其实 sql mock 只是实现了 go sql/driver 的接口,用于模拟数据库的连接,本质上并不会进行存储数据,只能特定的返回。

实际栗子

通过 sqlmock 测试创建 user 的sql语句

package main


import (
  "github.com/DATA-DOG/go-sqlmock"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
  "testing"
)


type User struct {
  ID int64 `gorm:"column:id"`
  UserName string `gorm:"column:user_name"`
}


func (User) TableName() string {
  return "users"
}


func CreateUser(db *gorm.DB, user *User) error{
  return db.Table(user.TableName()).Create(&user).Error
}


const (
  rawSQLCreateUser = "INSERT INTO `users` (`user_name`,`id`) VALUES (?,?)"
)


func TestShouldUpdateStats(t *testing.T) {
  db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  if err != nil {
    t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  }
  defer db.Close()
  dialector := mysql.New(mysql.Config{
    DriverName:                "mysql",
    Conn:                      db,
    SkipInitializeWithVersion:true,
  })
  user := &User{
    ID:       1,
    UserName: "zr",
  }
  gdb, err := gorm.Open(dialector, &gorm.Config{})
  gdb = gdb.Debug()
  mock.ExpectBegin()
  mock.ExpectExec(rawSQLCreateUser).
    WithArgs(user.UserName,user.ID).WillReturnResult(sqlmock.NewResult(1, 1))
  mock.ExpectCommit()
  if err = CreateUser(gdb, user); err != nil {
    t.Errorf("gorm create fail, err=%v", err)
  }
  if err = mock.ExpectationsWereMet(); err != nil {
    t.Errorf("unexcept sql, err=%v", err)
  }
}

总结

PS:笔者的老板对 sql 治理比较看重,所以在业务实现中会在存储层对于每一个 sql 写 sqlmock。

sqlmock 虽然不能对整个业务功能进行集成测试,但是在 dao 层,对存储数据的操作进行 sql 语句层面的校验个人觉得是有必要的,一方面这会使 sql 的管理更加高效(将定义的 rawsql 单独放在一个文件中),另一方面,数据库层面改动时,有完整的 sql 校验逻辑,方便 review 的人直观的看出来具体数据有什么变化。

顺带一提:这个库的开源作者想要找个开源维护者,感兴趣的也可以参与尝试下。

参考

github: 

https://github.com/DATA-DOG/go-sqlmock

往期推荐

d9c902e623a0b073a9f47f2451aff7f5.png

Categraf - 夜莺监控发布新轮子

520ad8dbaba998ae3ecb88be9ee80cb3.png

范型下,优雅的 Lodash 风

52cc2c0d65360e5131669141708d5f2b.png

API设计中性能提升的10个建议

想要了解Go更多内容,欢迎扫描下方👇 关注 公众号,回复关键词 [实战群]  ,就有机会进群和我们进行交流~

ccef0eabb28947456d2d2d9b68dc6f47.png

分享、在看与点赞,至少我要拥有一个叭~

6e8cf5a44a8cd69edef4ec0d35e3ab80.gif

3fa9249743acafd1bfcde48fe36515b3.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值