xorm和sqlmock结合的踩坑指南

  • Post author:
  • Post category:其他


首先明确一点:


xorm

中查询多条数据可以使用

Find

方法,Find方法的第一个参数为

slice的指针



Map指针


举个例子:

// 错误示例
var person []Person
db.where("age = ?", 18).Find(person) // 错误,得传person的地址,尽管person是指针类型// 正确示例
var person []Person
db.where("age = ?", 18).Find(&person)

如果以上这点没注意到,那么应结合

Find

函数返回的报错信息进行检测,报错信息很重要,能帮助我们排查错误。比如

engine.ShowSQL(true)

语句不生效,SQL语句打印不出来,很可能是执行SQL前那个函数报错了。

接下进入正题,先看看下面代码:

type Person struct {
    Age int `xorm:"not null"`
    Sex string `xorm:"not null"`
}func GetPerson(db *xorm.Engine, age int) []*Person {
    var p []*Person
    err := db.Where("age = ?", age).Limit(1).Find(&p)
    if err != nil {
        fmt.Println(err.Error()) // 很重要,这步错误处理不要省略,帮助定位问题
    }
    return p
}
func TestGetPerson(t *testing.T) {
    db, mock, _ := sqlmock.New()
    defer db.Close()
    mock.ExpectBegin()
    row := sqlmock.NewRows([]string{"age", "sex"}).AddRow(18, "男")
    mock.ExpectQuery("^SELECT \\* FROM `person` where age = \\?").WillReturnRows(row)
    engine,_ := xorm.NewEngine("mysql", "root:123@/test?charset=utf-8")
    engine.ShowSQL(true)
    engine.DB().DB = db
    p := GetPerson(engine, 18)
    fmt.Println(p)
}

上述代码中,GetPerson中报错信息显示:


call to Query ‘SELECT `age`, `sex` FROM `person` WHERE (age = ?) LIMIT 1’ with args [{Name: Ordinal:1 Value:18}], was not expected, next expectation is: ExpectedBegin => expecting database transaction Begin


这段报错表示

ExpectQuery

函数中传递的正则语句与实际执行的SQL语句没有匹配,根据这段报错信息或打印出来的SQL语句,应该将正则改为:


mock.ExpectQuery(“SELECT `age`, `sex` FROM `person` WHERE \\(age = \\?\\) LIMIT 1”)


或者再简单一点:


mock.ExpectQuery(“SELECT .* FROM `person`”)


只要正则匹配都行。

上述代码还有一个错误,那就是缺少

engine.DB().Begin()

。其实段语句可要可不要,视情况而定。当出现了

mock.ExpectBegin()

时,需要加上

engine.DB().Begin()

,否则不加。因为这两个语句是相匹配的,默认匹配,就像正则一样。

正确精简的版本:

type Person struct {
    Age int `xorm:"not null"`
    Sex string `xorm:"not null"`
}func GetPerson(db *xorm.Engine, age int) []*Person {
    var p []*Person
    err := db.Where("age = ?", age).Limit(1).Find(&p)
    if err != nil {
        fmt.Println(err.Error())
    }
    return p
}func TestGetPerson(t *testing.T) {
    db, mock, _ := sqlmock.New()
    defer db.Close()
    row := sqlmock.NewRows([]string{"age", "sex"}).AddRow(18, "男")
    mock.ExpectQuery("SELECT .* FROM `person`").WillReturnRows(row)
    engine,_ := xorm.NewEngine("mysql", "root:123@/test?charset=utf-8")
    engine.ShowSQL(true)
    engine.DB().DB = db
    p := GetPerson(engine, 11)
    if len(p) > 0 {
        fmt.Println(p[0])
    }
}



版权声明:本文为qq_40760732原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。